Evg*_*nik 5 dependency-injection mef nlog inversion-of-control
我想知道将NLog与托管可扩展性框架(MEF)一起使用的最佳方法是什么?
我有一个支持使用MEF架构(导入和导出等)插件的应用程序我想为我的应用程序添加日志记录功能.作为日志记录组件,我想使用NLog.
你会推荐什么?1.为NLog创建一个包装器,即配置NLog的其他插件,并导出其他插件导入的void Log(字符串级别,字符串消息)等函数.每个插件都应该拥有自己配置和使用的NLog实例.(他们都会写到同一个文件).
这是一个有趣的方法,然而,它似乎有一个缺点,即注入的所有记录器(或注入的一个单独的)将是相同的实例(或将具有相同的名称,名称是NLogLoggingService类.这意味着你不能很容易地控制日志记录的粒度(即在一个类中将日志记录转换为"Info"级别,在另一个类中转换为"Warn").另外,如果您选择使用调用站点格式化令牌,那么将始终将呼叫的呼叫站点作为NLog记录器而不是应用程序代码中的呼叫站点.
以下是链接的记录器的缩写版本:
[Export(Services.Logging.LoggingService, typeof(ILoggingService))]
class NLogLoggingService : ILoggingService
{
Logger log; public NLogLoggingService()
{
log = LogManager.GetCurrentClassLogger();
}
public void Debug(object message)
{
log.Debug(message);
}
public void DebugWithFormat(string format, params object[] args)
{
if (args.Length == 0)
{
log.Debug(format);
}
else
{
Debug(string.Format(format, args));
}
}
public bool IsDebugEnabled
{
get
{
return log.IsDebugEnabled;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在构造函数LogManager.GetCurrentClassLogger()中用于获取NLog记录器.GetCurrentClassLogger将返回一个NLog记录器,它根据"当前"类型"命名",在本例中为NLogLoggingService.因此,要在app.config文件中配置NLog,您将根据记录器名为"SoapBox.Core.NLogLoggingService"进行配置.通常,在直接使用NLog(或log4net)的代码中,每个类都有自己的唯一命名记录器,如下所示:
namespace MyNamespace
{
public class MyClass1
{
private static readonly Logger logger LogManager.GetCurrentClassLogger();
public void DoSomeWork()
{
logger.Info("Logging from inside MyClass1.DoSomeWork");
}
}
public class MyClass2
{
private static readonly Logger logger LogManager.GetCurrentClassLogger();
public void DoSomeWork()
{
logger.Info("Logging from inside MyClass2.DoSomeWork");
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,MyClass1和MyClass2的日志记录是可单独控制的.您可以为每个类配置不同的级别,将它们发送到不同的目标,或者完全关闭一个或两个级别.或者,由于log4net和NLog中记录器层次结构的概念,您可以通过为命名空间(本例中为MyNamespace)或任何"祖先"命名空间配置"记录器"来同时控制两个类中的记录.如果没有为完全限定的类型名配置记录器,则日志记录框架实质上是通过将名称设置为点分隔字符串并删除最后一个块并检查是否已配置该记录器来向上移动层次结构.因此,在这种情况下,我们要求MyNamespace.MyClass1和MyNamespace.MyClass2的记录器.我可以配置应用程序.配置文件让MyNamespace登录"info"并写入文件目标(log4net-speak中的appender).如果我这样做,那么我通过其完全限定名称请求的两个记录器都将继承MyNamespace配置.
使用建议的通过MEF注入NLog的方法,您将只有一个记录器实例,因此您不能将每个类配置为以不同方式记录.此外,正如我之前提到的,如果您选择记录调用站点信息,您将始终获得该类的"SoapBox.Core.NLogLoggingService"和该方法的"Debug"(或DebugWithFormat,或Info或InfoWithFormat等).
这似乎是从log4net和NLog成功注入记录器的问题.你可以看到的问题,我一个几个月前问这个非常问题.
最后,我能够弄清楚一些依赖注入框架如何成功注入特定于正在创建的类的log4net和NLog记录器(即,如果DI框架实例化MyClass,而MyClass又依赖于ILogger接口,那么MyClass将获得一个记录器,它基本上等同于MyClass通过LogManager.GetCurrentClassLogger api请求记录器本身时发生的记录器.通常,DI/IoC框架中的"解析器"被赋予当前上下文(包含当前正在创建的对象的类型等信息).有了这种类型,一个简单的问题就是让特定于日志框架的解析器接收该类型并将其传递给日志框架以创建适合该类型的记录器.
为了充分利用NLog(和log4net)的功能,你真的希望能够告诉MEF你的类依赖于"ILogger",而且注入你的类的"ILogger"实例也应该取决于你班级的类型.
我不知道用MEF实现这一目标是多么容易.或者,您可以将NLog的静态LogManager包装在ILogManager中并注入它.这将偏离正常的"注入ILogger"范式.
总结一下:如果以这种方式通过MEF注入NLog,您确实可以使用NLog进行日志记录,但是您只能拥有一个命名的记录器(SoapBox.Core.NLogLoggingService).这意味着您将无法以任何粒度控制 - 无论是级别/开/关还是输出(NLog Target/log4net Appender)
就通过MEF注入NLog并保持"原始"NLog为您提供的粒度/灵活性而言,我没有一个好的答案.
我可以说我们已经决定使用Common.Logging for .NET来抽象日志框架,但我们决定不注入日志记录.相反,我们将使用静态LogManager(由Common.Logging提供)来分发记录器.
| 归档时间: |
|
| 查看次数: |
4676 次 |
| 最近记录: |