我有兴趣了解更多关于人们如何使用依赖注入平台注入日志的知识。虽然下面的链接和我的示例都提到了log4net和Unity,但我不一定会使用其中的任何一个。对于依赖注入/ IOC,我可能会使用MEF,因为这是项目其他部分(大)正在解决的标准。我很新的依赖注入/ ioc,并且对于C#和.NET来说很新(在VC6和VB6的过去10年左右,C#/ .NET中已经写了很少的生产代码)。我已经对各种各样的日志解决方案进行了很多调查,所以我认为我对他们的功能集有很好的把握。我只是不太熟悉用实际的机制来获得一个依赖注入(或者,也许更“正确地”,得到一个注入的依赖注入的抽象版本)。依赖注入和命名记录器
我已经看到了相关的记录和/或依赖注入其他职位,如: dependency injection and logging interfaces
What would a Log4Net Wrapper class look like?
again about log4net and Unity IOC config
我的问题没有专门做“如何使用ioc工具yyy注入日志记录平台xxx?“相反,我感兴趣的是人们如何处理包装日志平台(通常,但并不总是推荐)和配置(即app.config)。例如,使用log4net的作为一个例子,我可以配置(在app.config)中的一些记录器中,然后在使用这样的代码的标准方法得到的那些记录器(不依赖注入):
private static readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
替代地如果我的记录是未命名的一类,而是一个功能区域,我可以这样做:
private static readonly ILog logger = LogManager.GetLogger("Login");
private static readonly ILog logger = LogManager.GetLogger("Query");
private static readonly ILog logger = LogManager.GetLogger("Report");
所以,我想,我的“要求”将是这样的:
我想将我的产品的来源与日志平台的直接依赖关系隔离开来。
我希望能够通过某种依赖注入(可能是MEF)直接或间接地解析特定的命名记录器实例(可能在同一命名实例的所有请求者之间共享相同的实例)。
我不知道我是否会称这是一个困难的要求,但我希望能够根据需要获得一个命名记录器(不同于类记录器)。例如,我可能会根据班级名称为我的班级创建一个记录器,但是一种方法需要特别严格的诊断,我想单独控制这些诊断。换句话说,我可能希望单个类“依赖”两个独立的记录器实例。
让我们从数字1开始。我已经阅读了很多文章,主要是关于stackoverflow,关于它是否是一个好主意换行。请参阅上面的“最佳实践”链接,并转至jeffrey hantin的评论,以获取有关为什么打包log4net很糟糕的观点。如果你真的包装了(如果你能有效地包装)你会严格包装注入/消除直接歧视的目的?或者你还会尝试抽象掉一些或全部log4net app.config信息?假设我想要使用System.Diagnostics,我可能想要实现一个基于接口的记录器(甚至可能使用“常见的”ILogger/ILog接口),可能基于TraceSource,这样我就可以注入它。您是否会通过TraceSource实现接口,并按原样使用System.Diagnostics app.config信息?
事情是这样的:
public class MyLogger : ILogger
{
private TraceSource ts;
public MyLogger(string name)
{
ts = new TraceSource(name);
}
public void ILogger.Log(string msg)
{
ts.TraceEvent(msg);
}
}
而且使用这样的:
private static readonly ILogger logger = new MyLogger("stackoverflow");
logger.Info("Hello world!")
移动到2号......如何解决一个特定的命名记录器实例?我是否应该利用我选择的日志平台的app.config信息(即根据app.config中的命名方案解析记录器)?所以,在log4net的情况下,我可能更喜欢“注入”LogManager(请注意,我知道这是不可能的,因为它是一个静态对象)?我可以打包LogManager(称为MyLogManager),给它一个ILogManager接口,然后解析MyLogManager.ILogManager接口。我的其他对象可能在ILogManager上有一个依赖关系(用MEF的说法导入)(从它实现的程序集导出)。现在我可以有这样的对象:
public class MyClass
{
private ILogger logger;
public MyClass([Import(typeof(ILogManager))] logManager)
{
logger = logManager.GetLogger("MyClass");
}
}
任何时候调用ILogManager,它都会直接委托给log4net的LogManager。或者,包装的LogManager能否根据app.config获取ILogger实例,并将它们按名称添加到(a?)MEF容器中。稍后,如果请求具有相同名称的记录器,则会为该名称查询包装的LogManager。如果ILogger在那里,就这样解决。如果MEF可以做到这一点,那么这样做有没有什么好处?
在这种情况下,实际上只有ILogManager是“注入”的,它可以按照log4net的正常方式发出ILogger实例。这种类型的注入(本质上是工厂)与注入指定的记录器实例相比如何?这确实可以更轻松地利用log4net(或其他日志平台)app.config文件。
我知道,我能得到命名实例出这样的MEF容器:
var container = new CompositionContainer(<catalogs and other stuff>);
ILogger logger = container.GetExportedValue<ILogger>("ThisLogger");
但如何获取命名实例放入容器?我知道基于属性的模型,我可以有不同的ILogger实现,每个实例都被命名(通过MEF属性),但这对我没有任何帮助。有没有办法像app.config(或其中的一部分)那样创建类似于记录器(所有相同的实现)的名称,并且MEF可以读取?可以/应该有一个中央“管理器”(如MyLogManager),通过底层app.config解析命名的记录器,然后将解析的记录器插入到MEF容器中?这样,对于有权访问相同MEF容器的其他人可以使用它(尽管没有MyLogManager了解如何使用log4net的app.config信息,似乎该容器将无法直接解析任何指定的记录器)。
这已经变得很长了。我希望它是连贯的。请随意分享关于您如何依赖注入日志平台的任何特定信息(我们很可能将log4net,NLog或基于System.Diagnostics构建的某些内容(希望很细)考虑到您的应用程序中。
你注入了“管理器”并让它返回记录器实例吗?
您是否在自己的配置部分或DI平台的配置部分中添加了一些自己的配置信息,以便于/可以直接插入记录器实例(即使您的依赖项位于ILogger而不是ILogManager上)。
如何让一个静态或全局容器具有ILogManager接口或其中的一组命名的ILogger实例。因此,不是按照常规的意义(通过构造函数,属性或成员数据)进行注入,而是根据需要明确解决日志依赖性问题。这是依赖注入的好方法还是坏方法?
我把这个标记为一个社区wiki,因为它看起来不像一个有明确答案的问题。如果任何人有其他感觉,请随时更改。
感谢您的帮助!
看起来像MEF和Unity(来自MS的Patterns&Practices组的IoC)就像比较苹果和橘子。也许一个真正的IoC容器是这个特定问题所需要的,它将具有可扩展性来添加自定义依赖性解决方案。 http://stackoverflow.com/questions/293051/is-mef-a-dependency-injection-framework – 2012-12-28 18:42:31