是否应该将日志框架注入需要它们的类中,或者每个需要它的类是否只需要知道框架并直接使用它?我正在使用Log4Net,目前我正在注入一个服务,将该框架包装到需要能够记录的类中,知道日志记录可能不会改变,大多数部分需要它,从这个意义上注入了答案吗? / p>
答案 0 :(得分:2)
从长远来看,注射更灵活,因为您可以轻松选择性地注入某些位置并有选择地禁用日志记录等。
答案 1 :(得分:1)
我认为注射它并没有错。他们建议仅仅出于性能原因使用静态变量,但我发现这与开始时注入记录器之间没有什么区别。
答案 2 :(得分:1)
如果内存性能不是很大的问题,您可以考虑使用AOP,例如:使用PostSharp。这样你的类根本不需要知道记录器。您基本上将IL-code作为postbuild步骤注入到程序集中。 PostSharp使用属性来标记方法,类甚至整个程序集。对于日志记录问题,甚至有plugin使用log4net。
编辑: 我提到了内存,因为每个属性都为每个连接点创建一个新对象。
答案 3 :(得分:1)
即使你说日志记录不会改变,我建议从特定的日志框架中抽象出来。但是,在所有情况下都不需要注入记录器实例。
以CommonLogging为例(参见this Stackoverflow answer以获取Common.Logging的简短描述)例如:您的类直接与工厂(LoggerManager)对话,但您不受特定记录器实现的约束
答案 4 :(得分:0)
如果你正在谈论依赖注入(比如在Spring.NET意义上),那么它并不重要 - 尽管你没有从多个logger实例副本中获得太多价值。通常,具有特定类/名称的框架返回的每个记录器实例无论如何都将是单例,因此问题是您是否希望使用记录器引用来混淆每个实例,而不是每个类的单个静态引用。如果您担心更改记录器实现,请登录到接口(CommonLogging,在另一个答案中提到,执行此操作,并支持log4net和Enterprise Library实现)。
如果你在谈论使用AOP注射,那么我不确定超过某一点,AOP注射更灵活。您几乎只限于使用方法级粒度记录入口,出口和异常。即使您使用AOP选择性地注入代码的一部分,AOP注入也是一种散射方法。虽然伐木被认为是AOP理想的交叉问题,但我从未发现基于AOP的测井在实践中有很大用处(当然是YMMV)。
答案 5 :(得分:0)
我很好奇你是如何注入Log4net的?请参阅我的问题/社区维基here。
我也看到了你对DI / Log4net问题的回答here。
我见过的大多数日志注入示例都显示了一个注入了“logger”的类,如下所示:
public class Foo
{
private ILogger logger;
public Foo(ILogger logger) //Injection via constructor
{
//Which "named" logger is this anyway? Is it Foo's? If so, how is it Foo's?
this.logger = logger;
}
public DoSomeWork(int xyz)
{
logger.Info("xyz = {0}", xyz);
}
}
使用像Log4net(和NLog,以及其他人)这样的东西,你通常会创建一个这样的记录器:
public class Foo
{
private static ILogger logger =
LogManager.GetLogger(
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public Foo()
{
}
public DoSomeWork(int xyz)
{
logger.Info("xyz = {0}", xyz);
}
}
那么,如果依赖注入,我的班级Foo如何获得正确的记录器?另外,也许我没有严格根据课程命名我的记录器。相反,我可能会根据可能无法从类型派生的功能区域(如“DatabaseAccess”,“AppStartup”,“AppShutdown”等)来命名它们。
您是注入“Logger”(对应于命名的记录器)还是“LogManager”(对应于Log4net的LogManager),或者您正在做其他事情?您是否使用DI平台的配置功能来关联注入依赖项的“命名实例”?我认为Unity支持这样的东西,虽然我不太确定。
以下是我想象注入“LogManager”的方法:
public class Foo
{
private static ILogger logger;
public Foo(ILogManager logManager) //Injection via constructor
{
logger = logManager.GetLogger
(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
//Since logger is (should it be?) static, maybe should be like this:
if (logger = null)
{
logManager.GetLogger
(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
}
}
public DoSomeWork(int xyz)
{
logger.Info("xyz = {0}", xyz);
}
}
在我看来,注入像ILogManager(其实现将包装Log4net的LogManager)之类的东西比注入ILogger更容易,因为DI平台将如何知道要注入哪个ILogger的问题。
我是DI和.NET日志记录平台的新手(实际上,对于C#和.NET来说一般都是新手)。我过去多年的绝大部分经验是VB6 + VC ++ 6。
感谢您提供任何信息......
开始编辑...
我已经了解了更多,并且发现你也问过AutoFac,所以我猜你正在使用它来做你的DI。如果这是真的,那么我猜你也在做类似this的事情,或者显然更好,比如this来解决你的记录器(按类类型)。我想这回答了至少在AutoFac中如何注入命名记录器(例如来自Log4Net或NLog)的问题。
结束编辑...