依赖注入和命名伐木者 [英] Dependency injection and named loggers

查看:185
本文介绍了依赖注入和命名伐木者的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有兴趣了解更多关于注射的人如何与依赖注入平台的日志记录。虽然下面的链接,和我的例子是指log4net的和Unity,我不一定要去为使用那些。对于依赖注入/ IOC,我可能会使用MEF,因为这是该项目的剩余部分(大)则沉降于标准。

I am interested in learning more about how people inject logging with dependency injection platforms. Although the links below and my examples refer to log4net and Unity, I am not necessarily going to use either of those. For dependency injection/IOC, I will probably use MEF as that is the standard that the rest of the project (large) is settling on.

我很新的依赖注入/ IOC和上午pretty新的C#和.NET(已在C#/。NET后,在过去的10年左右的VC6和VB6编写很少生产code。 )。我已经做了很多的调查到的各种记录的解决方案是在那里,所以我认为我对他们的功能集一个体面的句柄。我只是不熟悉够注射获得一个依赖的实际力学(或者,也许更多正确,得到一个相关性的抽象版本注入)。

I am very new to dependency injection/ioc and am pretty new to C# and .NET (have written very little production code in C#/.NET after the past 10 years or so of VC6 and VB6). I have done a lot of investigation into the various logging solutions that are out there, so I think that I have a decent handle on their feature sets. I am just not familiar enough the with actual mechanics of getting one dependency injected (or, maybe more "correctly", getting an abstracted version of one dependency injected).

我已经看到了相关的记录和/或依赖注入像其他职位:
<一href=\"http://stackoverflow.com/questions/522370/dependency-injection-and-logging-interfaces\">http://stackoverflow.com/questions/522370/dependency-injection-and-logging-interfaces

I have seen other posts related to logging and/or dependency injection like: http://stackoverflow.com/questions/522370/dependency-injection-and-logging-interfaces

<一个href=\"http://stackoverflow.com/questions/576185/logging-best-practices\">http://stackoverflow.com/questions/576185/logging-best-practices

<一个href=\"http://stackoverflow.com/questions/166438/what-would-a-log4net-wrapper-class-look-like\">http://stackoverflow.com/questions/166438/what-would-a-log4net-wrapper-class-look-like

<一个href=\"http://stackoverflow.com/questions/1320844/again-about-log4net-and-unity-ioc-config\">http://stackoverflow.com/questions/1320844/again-about-log4net-and-unity-ioc-config

我的问题并没有专门与做如何我使用注入工具奥委会YYY测井平台XXX?相反,我感兴趣的是人们如何处理包装记录平台(这是常有的,但并不总是推荐)和配置(即app.config)中。例如,使用log4net的作为一个例子,我可以配置(以app.config)中的一些伐木工人,然后使用code这样的标准方式获得这些记录仪(不依赖注入):

My question does not have specifically to do with "How to I inject logging platform xxx using ioc tool yyy?" Rather, I am interested in how people have handled wrapping the logging platform (as is often, but not always recommended) and configuration (i.e. app.config). For example, using log4net as an example, I could configure (in app.config) a number of loggers and then get those loggers (without dependency injection) in the standard way of using code like this:

private static readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

另外,如果我的记录是未命名的一类,而是一个功能区域,我可以这样做:

Alternatively, if my logger is not named for a class, but rather, for a functional area, I could do this:

private static readonly ILog logger = LogManager.GetLogger("Login");
private static readonly ILog logger = LogManager.GetLogger("Query");
private static readonly ILog logger = LogManager.GetLogger("Report");

所以,我想,我的要求将是这样的:

So, I guess that my "requirements" would be something like this:


  1. 我想从一个记录平台的直接依赖隔离我的产品的来源。

  1. I would like to insulate my product's source from a direct dependency on a logging platform.

我希望能够直接或间接地通过某种依赖注入,可能是MEF的解决特定的命名记录器实例(可能共享同一个命名实例的所有请求者之间的同一个实例)。

I would like to be able to resolve a specific named logger instance (probably sharing the same instance among all requesters of the same named instance) either directly or indirectly by some kind of dependency injection, probably MEF.

我不知道我是否愿意称之为硬性要求,但我想获得按需指定logger(不是类记录仪不同)的能力。例如,我可以创建基于类的名字我班记录器,而是一个方法需要格外沉重的诊断,我想单独控制。换句话说,我可能要一个类在两个独立的记录器实例靠。

I don't know if I would call this a hard requirement, but I would like the ability to get a named logger (different than the class logger) on demand. For example, I might create a logger for my class based on the class name, but one method needs particulary heavy diagnostics that I would like to control separately. In other words, I might want a single class to "depend" on two separate logger instances.

让我们开始与数字1。我读了一些文章,主要是在这里计算器,关于它是否是包装一个好主意。请参阅最佳实践链接上方,然后转到杰弗里hantin 的评论一个观点,为什么它是坏的包log4net的。如果你没有包装(如果你能有效地包好),你会严格包装注射/去除直接depdency的目的是什么?或者,你也尽量抽象掉部分或全部的log4net的的app.config信息?

Let's start with number 1. I have read a number of articles, primarily here on stackoverflow, about whether or not it is a good idea to wrap. See the "best practices" link above and go to jeffrey hantin's comment for one view about why it is bad to wrap log4net. If you did wrap (and if you could wrap effectively) would you wrap strictly for the purpose of injection/removal of direct depdency? Or would you also try to abstract away some or all of the log4net app.config information?

比方说,我想用System.Diagnostics程序,我可能会想实现一个基于接口的记录(甚至使用常用ILogger / ILog的接口),可能是基于TraceSource,这样我就可以注入它。你会实现接口,多说TraceSource,只是使用System.Diagnostics程序的app.config信息是什么?

Let's say I want to use System.Diagnostics, I would probably want to implement an interface-based logger (maybe even using the "common" ILogger/ILog interface), probably based on TraceSource, so that I could inject it. Would you implement the interface, say over TraceSource, and just use the System.Diagnostics app.config information as is?

事情是这样的:

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的情况下,也许我preFER注入日志管理(请注意,我知道,因为它是一个静态对象,这是不可能的)?我可以换日志管理(称之为MyLogManager),给它一个ILogManager接口,然后解决MyLogManager.ILogManager接口。我的其他对象可以有一个depenency上ILogManager(进口在MEF说法)(从它实施的组装出口)。现在我能有这样的对象:

Moving on to number 2 ... How to resolve a particular named logger instance? Should I just leverage the app.config information of the logging platform that I choose (i.e. resolve the loggers based on the naming scheme in the app.config)? So, in the case of log4net, might I prefer to "inject" LogManager (note that I know this is not possible since it is a static object)? I could wrap LogManager (call it MyLogManager), give it an ILogManager interface, and then resolve MyLogManager.ILogManager interface. My other objects could have a depenency (Import in MEF parlance) on ILogManager (Export from the assembly where it is implemented). Now I could have objects like this:

public class MyClass
{
  private ILogger logger;
  public MyClass([Import(typeof(ILogManager))] logManager)
  {
    logger = logManager.GetLogger("MyClass");
  }
}

任何时候ILogManager被调用时,它会直接委托给log4net的的日志管理。另外,可以在包裹的LogManager采取它就会基于在app.config的ILogger实例,并通过名称将它们添加到(一个?)MEF容器。之后,当被请求的相同名称的记录器,被包覆的LogManager查询该名称。如果ILogger是存在的,它解决的方式。如果这是可能的MEF,有什么好处不这样做?

Any time ILogManager is called, it would directly delegate to log4net's LogManager. Alternatively, could the wrapped LogManager take the ILogger instances that it gets based on the app.config and add them to the(a ?) MEF container by name. Later, when a logger of the same name is requested, the wrapped LogManager is queried for that name. If the ILogger is there, it is resolved that way. If this is possible with MEF, is there any benefit do doing so?

在这种情况下,说真的,只有ILogManager被注入,它可以在log4net的不正常的方式分发ILogger实例。请问这个类型注入(本质上是一个工厂)的比较注入指定logger实例?这确实允许的log4net的更容易杠杆(或其他测井平台)app.config文件。

In this case, really, only ILogManager is "injected" and it can hand out ILogger instances in the way that log4net normally does. How does this type of injection (essentially of a factory) compare to injecting the named logger instances? This does allow for more easy leveraging of log4net's (or other logging platform) app.config file.

我知道我能得到命名实例像这样的MEF容器:

I know that I can get named instances out of the MEF container like this:

var container = new CompositionContainer(<catalogs and other stuff>);
ILogger logger = container.GetExportedValue<ILogger>("ThisLogger");

但我怎么拿到命名实例放入容器中?我知道属性基于模型在那里我可以有ILogger的不同实现,每一个被命名为(通过MEF属性),但是,这并不真正帮助我。有没有一种方法来创造这样一个app.config(或其中的部分),将列出了名称和MEF记录仪(所有相同的实施)能读懂?可以/应该有一个中心经理(如MyLogManager),它通过底层的app.config解决命名记录器,然后插入记录解析到MEF容器?这种方式,将提供给他人能够访问相同的MEF容器(尽管没有说明如何使用的log4net的的app.config信息MyLogManager的知识,似乎该容器将无法直接解决任何命名记录器)。

But how do I get the named instances into the container? I know about the attribute based model where I could have different implementations of ILogger, each of which is named (via a MEF attribute), but that doesn't really help me. Is there a way to create something like an app.config (or a section therein) that would list the loggers (all of the same implementation) by name and that MEF could read? Could/should there be a central "manager" (like MyLogManager) that resolves named loggers via the underlying app.config and then inserts the resolved logger into the MEF container? This way it would be available to someone else that has access to the same MEF container (although without the MyLogManager's knowledge of how to use log4net's app.config information, it seems that the container would be unable to resolve any named loggers directly).

这已经得到了长pretty。我希望这是一致的。请随时分享你的依赖注入如何测井平台(我们最有可能考虑log4net的,NLOG,或东西(希望瘦)建立在System.Diagnostics程序)到您的应用程序的任何具体信息。

This has already gotten pretty long. I hope it that it is coherent. Please feel free to share any specific information about how you dependency injected a logging platform (we are most likely considering log4net, NLog, or something (hopefully thin) built on System.Diagnostics) into your application.

你注入经理,并使其返回记录器实例?

Did you inject the "manager" and have it return logger instances?

你加一些你自己的配置信息,在自己的配置部分还是在你的DI平台的配置部分,使其更容易/可能直接注入记录器实例(即让你的依赖是对ILogger,而不是ILogManager)。

Did you add some of your own config information in your own config section or in your DI platform's config section to make it easier/possible to inject logger instances directly (i.e. make your dependencies be on ILogger rather than ILogManager).

关于有有无论是在它的ILogManager接口或集,任命ILogger实例的静态或全球集装箱什么。因此,而不是传统意义上的注入(通过构造函数,属性或成员数据),记录依赖关系明确解决的需求。这是依赖注入好坏的方法。

What about having a static or global container that has either the ILogManager interface in it or the set of named ILogger instances in it. So, rather than injecting in the conventional sense (via constructor, property, or member data), the logging dependency is explicitly resolved on demand. Is this a good or bad way to dependency inject.

我标志着这是一个社区维基,因为它似乎并不像一个明确答案的问题。如果有人觉得,否则,随意去改变它。

I am marking this as a community wiki since it doesn't seem like a question with a definite answer. If anyone feels otherwise, feel free to change it.

感谢您的帮助!

推荐答案

这是任何人都试图找出如何注入依赖关系logger的好处时,将提供一个日志的平台,这样你要注入记录器作为log4net的或NLOG。我的问题是,我不明白我怎么能让一个类(如MyClass的)依赖一个ILogger型接口的时候我就知道,具体ILogger的分辨率将取决于明知是依赖于ILogger类的类型(例如MyClass的)。如何在DI / IoC的平台/容器得到正确的ILogger?

This is for the benefit of anyone that is trying to figure out how to inject a logger dependency when the logger that you want to inject is provided a logging platform such as log4net or NLog. My problem was that I could not understand how I could make a class (e.g. MyClass) dependent on an ILogger-type interface when I knew that the resolution of the specific ILogger would depend on knowing the type of the class that is dependent on ILogger (e.g. MyClass). How does the DI/IoC platform/container get the right ILogger?

唉,我看了看源城堡和NInject,并看到他们如何工作。我也看了AutoFac和StructureMap。

Well, I have looked at the source for Castle and NInject and have seen how they work. I have also looked AutoFac and StructureMap.

城堡和NInject都提供日志记录的实现。两者都支持log4net的和NLOG。城堡还支持System.Diagnostics程序。在这两种情况下,当平台解决给定对象的依赖关系(例如,当该平台创建MyClass的和MyClass的取决于ILogger)它代表的创建的依赖(ILogger)到ILogger提供者的(解析器可能是一个更常用词)。在ILogger提供商的实现则负责实际实例ILogger的一个实例,并移交回出来,再注入依赖类(如MyClass的)。在两种情况下,提供者/解析器知道从属类(例如MyClass的)的类型。因此,已创建MyClass的时候和它的依赖正在解决,ILogger解析知道了类是MyClass的。在使用城堡或NInject的情况下只要记录解决方案,这意味着,记录溶液(作为包装实施了log4net的或NLOG)得到式(MyClass的),因此它可以委派向下log4net.LogManager.GetLogger()或NLog.LogManager.GetLogger()。 (不是100%肯定语法log4net的和NLOG的,但你的想法)。

Castle and NInject both provide an implementation of logging. Both support log4net and NLog. Castle also supports System.Diagnostics. In both cases, when the platform resolves the dependencies for a given object (e.g. when the platform is creating MyClass and MyClass depends on ILogger) it delegates the creation of the dependency (ILogger) to the ILogger "provider" (resolver might be a more common term). The implementation of the ILogger provider is then responsible for actually instantiating an instance of ILogger and handing it back out, to then be injected into the dependent class (e.g. MyClass). In both cases the provider/resolver knows the type of the dependent class (e.g. MyClass). So, when MyClass has been created and its dependencies are being resolved, the ILogger "resolver" knows that the class is MyClass. In the case of using the Castle or NInject provided logging solutions, that means that the logging solution (implemented as a wrapper over log4net or NLog) gets the type (MyClass), so it can delegate down to log4net.LogManager.GetLogger() or NLog.LogManager.GetLogger(). (Not 100% sure of syntax for log4net and NLog, but you get the idea).

虽然AutoFac和StructureMap不提供日志工具(至少我可以通过寻找告诉),他们似乎提供实现自定义冲突解决的能力。因此,如果你想写你自己的日志抽象层,你也可以写一个相应的自定义解析器。这样,当容器要解决ILogger,您的解析器将用于获得正确ILogger与它必须访问当前上下文(即,什么对象的依赖关系,目前正在纳 - 什么目的是依赖ILogger)。获取对象的类型,你就可以委托给当前配置的日志平台创建ILogger的(你可能已经抽象的接口后面,您已写了一个解析器)。

While AutoFac and StructureMap do not provide a logging facility (at least that I could tell by looking), they do seem to provide the ability to implement custom resolvers. So, if you wanted to write your own logging abstraction layer, you could also write a corresponding custom resolver. That way, when the container wants to resolve ILogger, your resolver would be used to get the correct ILogger AND it would have access to the current context (i.e. what object's dependencies are currently being satisfied - what object is dependent on ILogger). Get the type of the object, and you are ready to delegate the creation of the ILogger to the currently configured logging platform (that you have probably abstracted behind an interface and for which you have written a resolver).

所以,要求一对夫妇,我怀疑是关键点,但我并没有完全掌握之前分别是:

So, a couple of key points which I suspected were required but that I did not fully grasp before are:


  1. 最后的DI容器必须
    知道,不知何故,什么记录
    平台来使用。通常,这是
    通过指定ILogger是做
    由一个解析进行解析
    是特定于一个记录平台
    (因此,城堡已经log4net的,NLOG,
    和System.Diagnostics程序解析器
    (等等))。该规范
    其中解析器使用可以做到
    通过配置文件或编程。

  1. Ultimately the DI container must be aware, somehow, of what logging platform to use. Typically this is done by specifying that "ILogger" is to be resolved by a "resolver" that is specific to a logging platform (hence, Castle has log4net, NLog, and System.Diagnostics "resolvers" (among others)). The specification of which resolver to use can be done via config file or programmatically.

解析器需要知道
    上下文其依赖
    (ILogger)正在被解决。那
    是,如果MyClass的已创建并
    它是依赖于ILogger,然后
    当解析器正试图
    建立正确的ILogger,它(
    解析器)必须知道当前类型
    (我的课)。这样,解析器
    可以使用底层记录
    实现(log4net的,NLOG等)
    以获得正确的记录。

The resolver needs to know the context for which the dependency (ILogger) is being resolved. That is, if MyClass has been created and it is dependent on ILogger, then when the resolver is trying to create the correct ILogger, it (the resolver) must know the current type (MyClass). That way, the resolver can use the underlying logging implementation (log4net, NLog, etc) to get the correct logger.

这点可能是显而易见的那些DI / IoC的用户在那里,但我刚才进入,所以它采取了我一段时间让我的头周围。

These points might be obvious to those DI/IoC users out there, but I am just now coming into it, so it has taken me a while to get my head around it.

这是我还没有想出但有一件事情是这样的事情怎么样,或者是可能的MEF。我有一个对象依赖一个接口上,然后让MEF已经创建的对象后,我的code执行并同时在接口/依赖性正在解决?因此,假设我有一个这样的类:

One thing that I have not figured out yet is how or if something like this is possible with MEF. Can I have an object dependent on an interface and then have my code execute after MEF has created the object and while the interface/dependency is being resolved? So, assume I have a class like this:

public class MyClass
{
  [Import(ILogger)]
  public ILogger logger;

  public MyClass()
  {
  }

  public void DoSomething()
  {
    logger.Info("Hello World!");
  }
}

在MEF被解析为MyClass的进口,可我有我自己的一些code(通过一个属性,通过关于ILogger实施额外的接口,其他???)执行和解决基于ILogger进口这样的事实,它是MyClass的是目前在上下文中和给回一(潜在地)不同ILogger比YourClass将检索到的实例?难道我实现某种MEF提供商?

When MEF is resolving the imports for MyClass, can I have some of my own code (via an attribute, via an extra interface on the implementation of ILogger, elsewhere???) execute and resolve the ILogger import based on the fact that it is MyClass that is currently in context and give back a (potentially) different ILogger instance than would be retrieved for YourClass? Do I implement some sort of MEF Provider?

在这一点上,我仍然不知道MEF。

At this point, I still don't know about MEF.

这篇关于依赖注入和命名伐木者的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆