È necessario definire un programma di registrazione proxy che instradi il messaggio al Nlog Logger corretto. Questo proxy è piuttosto semplice:
public class NLogProxy<T> : ILogger
{
private static readonly NLog.ILogger logger =
LogManager.GetLogger(typeof (T).FullName);
void ILogger.Log(string message)
{
logger.Log(LogLevel.Info, message);
}
}
È possibile registrare questo come
container.RegisterConditional(typeof(ILogger),
context => typeof(NLogProxy<>).MakeGenericType(context.Consumer.ImplementationType),
Lifestyle.Singleton, context => true);
ovunque bisogna accedere solamente dovrà iniettare ILogger
.
Come per AOP. Non sono sicuro di cosa intendi con questo commento
Un wrapper che deve essere mantenuto (il contratto di NLog.ILogger è enorme).
Logging è un cross cutting concern e utilizzando un decorator è un ottimo modo per applicare preoccupazioni trasversali. Con un decoratore non sarà possibile accedere a tutte le chiamate (private) di ingresso e uscita della chiamata, ma perché lo vuoi? Come puoi leggere here probabilmente non ne hai bisogno. Il semplice fatto che venga chiamato un servizio (con i dati passati a questo servizio) e le eventuali eccezioni vengono registrate con lo stacktrace completo sarà più che sufficiente nella maggior parte dei casi.
Quindi considerare questo:
public interface ISomeService
{
void DoSomething(string someParameter);
}
public class SomeServiceDecorator : ISomeService
{
private readonly ISomeService decoratee;
private readonly ILogger logger;
public SomeServiceDecorator(ISomeService decoratee, ILogger logger)
{
this.decoratee = decoratee;
this.logger = logger;
}
public void DoSomething(string someParameter)
{
try
{
this.logger.Log(string.Format("Do something called with {0}", someParameter));
this.decoratee.DoSomething(someParameter);
}
catch (Exception e)
{
this.logger.Log(e.ToString());
throw;
}
}
}
Questo decoratore registrerà tutte le chiamate di funzione con le informazioni passate al servizio e anche registrare alcuna eccezione.
Ma questo approccio aumenterebbe il numero di classi per 2, quindi non molto DRY. Questo problema è causato dal fatto che questo design è almeno subottimale. L'utilizzo di un progetto attorno a un'unica astrazione generica aperta risolverà completamente questo problema. È possibile leggere su questo design here e here.
In questo caso si avrebbe un unico `LoggingDecorator' come
public class LoggingCommandHandlerDecorator<T> : ICommandHandler<T>
{
private readonly ICommandHandler<T> decoratee;
private readonly ILogger logger;
public LoggingCommandHandlerDecorator(ICommandHandler<T> decoratee, ILogger logger)
{
this.decoratee = decoratee;
this.logger = logger;
}
public void Handle(T command)
{
// serialize command to json and log
this.logger.Log(serializedcommandData);
this.decoratee.Handle(command);
}
}
E questo singolo decoratore registrerà tutti i comandi.
Questa è la mia visione di AOP ....
cosa vorresti fosse il valore di 'loggerName'? – qujck
Correlati: https://stackoverflow.com/q/32952701/264697 – Steven
L'applicazione delle tecniche AOP è molto utile, ma si prega di stare lontano dagli strumenti di tessitura del codice. Applicare AOP utilizzando decoratori. Correlato: https://stackoverflow.com/a/9915056/264697 – Steven