使用 Simple Injector 註冊 NLog ILogger
有什麼方法可以獲取上下文,以便我可以檢索
loggerName並使用LogManager.GetLogger(loggerName)而不是LogManager.GetCurrentClassLogger()?我注意到
container.RegisterConditional()可以訪問上下文。另外,我現在想避免使用SimpleLogging.NLog 之類的解決方案。
最後,我願意接受這不是正確的做法。順便說一句,AOP 是我已經探索過的一個選項(將記錄器作為單例是一個好習慣嗎?)。
注意:我知道
GetCurrentClassLogger()獲得的資訊與使用 .NET 反射檢索的資訊相同。using NLog; using SimpleInjector; namespace DependencyInjection { class Program { private static Container _container; static void Main(string[] args) { Bootstrap(); _container.GetInstance<Greeter>().Greet(); } private static void Bootstrap() { _container = new Container(); _container.Register<ILogger>(() => LogManager.GetCurrentClassLogger(), Lifestyle.Transient); _container.Register<Greeter>(); _container.Verify(); } public class Greeter { private ILogger _logger; public Greeter(ILogger logger) { _logger = logger; } public void Greet() { _logger.Log(LogLevel.Info, "Hello world!"); } } } }
您需要定義一個代理記錄器,它將消息路由到正確的 Nlog 記錄器。這個代理很簡單:
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); } }您可以將其註冊為
container.RegisterConditional(typeof(ILogger), context => typeof(NLogProxy<>).MakeGenericType(context.Consumer.ImplementationType), Lifestyle.Singleton, context => true);任何你需要記錄的地方,你只需要注入
ILogger.至於AOP。我不確定你的評論是什麼意思
必須維護的包裝器(NLog.ILogger 契約很大)。
日誌記錄是一個橫切關注點,使用裝飾器是應用橫切關注點的好方法。使用裝飾器,不可能記錄每個(私有)函式呼叫入口和出口,但你為什麼要這樣呢?正如您可以在此處閱讀的那樣,您可能不需要它。在大多數情況下,呼叫服務(將數據傳遞給該服務)並使用完整的堆棧跟踪記錄可能的異常這一簡單事實將綽綽有餘。
所以考慮一下:
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; } } }此裝飾器將記錄所有函式呼叫以及傳遞給服務的資訊,還將記錄任何異常。
但是這種方法會將類的數量增加 2,所以不是很DRY。之所以會出現這個問題,是因為這種設計至少是次優的。使用圍繞單個開放通用抽象的設計將完全解決這個問題。您可以在此處和此處閱讀有關此設計的資訊。
在這種情況下,您將有一個“LoggingDecorator”作為
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); } }這個單一的裝飾器將記錄你所有的命令。
這就是我對 AOP 的看法……