2012-12-12 9 views
5

Pracuję nad dodaniem rejestrowania do projektu za pomocą Windsor Logging Facility i integracji NLog.Windsor Logging Facility: nazwa logu kontrolnego

Zamiast stosować się do zalecanej praktyki dokumentacji Windsor, dodającej właściwość Log do każdej klasy, dla której chcę obsługiwać rejestrowanie, zdecydowałem się spróbować zrobić to za pomocą dynamicznego przechwytywania. Jak dotąd przechwytujący jest dość prosty; to po prostu używa konstruktora wtrysku, aby uzyskać instancję ILogger:

class LoggingInterceptor : IInterceptor 
{ 
    private readonly ILogger _logger; 
    public LoggingInterceptor(ILogger logger) 
    { 
     if (logger == null) throw new ArgumentNullException("logger"); 
     _logger = logger; 
    } 

    public void Intercept(IInvocation invocation) 
    { 
     // just a placeholder implementation, I'm not actually planning to do this ;) 
     _logger.Info(invocation.Method.Name); 
     invocation.Proceed(); 
    } 
} 

poza tym, wszystko robiłem to minimalna dla rejestracji przechwytywania i stosując ją do komponentu, a obiekt rejestrowania dba o resztę .

container.Register(Component.For<LoggingInterceptor>().LifeStyle.Transient); 

container.Register(
    Component.For<IEmployeeRepository>() 
    .ImplementedBy<EmployeeRepository>() 
    .Interceptors(InterceptorReference.ForType<LoggingInterceptor>()).First); 

Jak dotąd tak dobrze - rodzaj. Logger, który otrzymuję, jest zgodny z zalecaną przez NLog praktyką jednego rejestratora dla każdej klasy. Nie sądzę, że to bardzo dobry wybór w tym przypadku. Oznacza to, że każda wiadomość przechodzi do dziennika o nazwie "MyApplication.Interceptors.LoggingInterceptor", co nie jest zbyt użyteczne.

Wolałbym mieć logi nazwane po abstrakcji, do której został zastosowany rejestrator. Jeśli na przykład rejestrator został zastosowany do implementacji IEmployeeRepository, dziennik powinien mieć nazwę EmployeeRepository. Czy to jest wykonalne?

Edit: Próbowałem realizacji niestandardowych ILoggerFactory i instruowania pojemnik go używać zamiast. Jednak szybko trafiłem na blokadę drogową: gdy Windsor wywołuje fabrykę, jedyną dostarczoną informacją jest typ obiektu, dla którego pozyskiwany jest rejestrator. Żadne inne informacje na temat obiektu nie są dostarczane, więc ILoggerFactory nie ma możliwości dowiedzenia się o abstrakcji, do której został zastosowany przechwytywacz.

Zauważam, że istnieją dwa przeciążenia ILoggerFactory.Create(), które akceptują ciągi jako argumenty. Windsor prawdopodobnie nie używa żadnego z nich bezpośrednio, ale można by założyć, że muszą tam być z jakiegoś powodu. Czy jest coś w płynnym interfejsie API, które można wykorzystać do określenia, że ​​dany łańcuch ma być używany?

Odpowiedz

6

Oto pytanie, które jest bardzo podobne do twojego i ma zaakceptowaną odpowiedź. W linku osoba wysyłająca odpowiedź sugeruje uzależnienie przechwytywacza od ILoggerFactory i metody Intercept, użyj parametru IInvocation.TargetType jako typu do wysłania do ILoggerFactory, aby uzyskać odpowiedni rejestrator.

Uwaga, nie używam Castle, więc nie mogę więcej komentować tej sugestii.

public class LoggingInterceptor : IInterceptor 
{ 
    private readonly ILoggerFactory _loggerFactory; 

    public LoggingInterceptor(ILoggerFactory loggerFactory) 
    { 
     _loggerFactory = loggerFactory; 
    } 

    public void Intercept(IInvocation invocation) 
    { 
     var logger = _loggerFactory.Create(invocation.TargetType); 
     if (logger.IsDebugEnabled) 
     { 
      logger.Debug(CreateInvocationLogString(invocation)); 
     } 
     try 
     { 
      invocation.Proceed(); 
     } 
     catch (Exception e) 
     { 
      logger.Warn(CreateInvocationLogString(invocation)); 
      throw; 
     } 
     logger.Info(CreateInvocationLogString(invocation)); 
    } 

    private static String CreateInvocationLogString(IInvocation invocation) 
    { 
     var sb = new StringBuilder(100); 
     sb.AppendFormat("Called: {0}.{1}(", invocation.TargetType.Name, invocation.Method.Name); 
     foreach (var argument in invocation.Arguments) 
     { 
      var argumentDescription = argument == null ? "null" : argument.ToString(); 
      sb.Append(argumentDescription).Append(","); 
     } 
     if (invocation.Arguments.Any()) 
     { 
      sb.Length--; 
     } 
     sb.Append(")"); 
     return sb.ToString(); 
    } 
} 

Castle: How can i get the correct ILogger in the logging interceptor?

Prawdopodobnie już widziałem tego, ale tu jest link do przykładu Castle, który pokazuje, jak stworzyć przechwytywania rejestrowania i jak, najwyraźniej, aby utworzyć rejestratora dla zawiniętego typu:

http://docs.castleproject.org/Windsor.Introduction-to-AOP-With-Castle.ashx

EDIT: realizacja ILoggerFactory dla NLog jest ExtendedNLogFactory, to w pakiecie Nuget Castle.Core-nlog (http://www.nuget.org/packages/Castle.Core-NLog)

+1

Twoje Google-fu jest zdecydowanie lepsze niż moje. To powinno być doskonałe - jedynym dodatkowym szczegółem jest uzyskanie logu o nazwie typu abstrakcyjnego, a nie typu konkretnego.Myślę, że zrobię to, przeszukując interfejsy typu konkretnego dla tych, które są zgodne z konwencją. –

+0

Cieszę się, że mogłem pomóc! – wageoghe