Gie*_*ius 75 .net c# logging singleton dependency-injection
我有习惯将记录器传递给构造函数,如:
public class OrderService : IOrderService {
public OrderService(ILogger logger) {
}
}
Run Code Online (Sandbox Code Playgroud)
但这很烦人,所以我已经使用了它一段时间了:
private ILogger logger = NullLogger.Instance;
public ILogger Logger
{
get { return logger; }
set { logger = value; }
}
Run Code Online (Sandbox Code Playgroud)
这也很烦人 - 它不干,我需要在每个班级重复这个.我可以使用基类,但是再次 - 我正在使用Form类,所以需要FormBase等等.所以我认为,暴露ILogger的单例会有什么不利因素,所以我们知道在哪里得到logger:
Infrastructure.Logger.Info("blabla");
Run Code Online (Sandbox Code Playgroud)
更新:正如Merlyn正确注意到的那样,我应该提一下,在第一和第二个例子中,我正在使用DI.
Dan*_*ose 37
我在我的依赖注入容器中放置了一个logger实例,然后将记录器注入需要它的类中.
Mer*_*ham 34
这也很烦人 - 它不是干的
确实如此.但是,只有你可以做的事情才能实现贯穿各种类型的贯穿各领域的关注.您必须在任何地方使用记录器,因此您必须拥有这些类型的属性.
所以让我们看看我们能做些什么.
单身人士很可怕<flame-suit-on>
.
我建议您坚持使用属性注入,因为您已经完成了第二个示例.这是你无需借助魔法就可以做到的最好的因素.拥有显式依赖关系比通过单例隐藏它更好.
但是如果单身人士为你节省了大量时间,包括你将不得不做的所有重构(水晶球时间!),我想你可以和他们一起生活.如果有一个单身人士的用途,这可能是它.记住的成本,如果你曾经想改变你的思想会约高,因为它得到.
如果你这样做,看看别人的答案使用的Registry
模式(见说明书),而那些注册(可复位)单工厂,而不是一个单独的记录器实例.
除了妥协之外,还有其他替代方案可以正常工作,因此您应该首先检查它们.
您可以使用Visual Studio代码片段来加速重复代码的输入.您将能够键入类似的内容logger
tab,代码将神奇地为您显示.
您可以使用像PostSharp这样的面向方面编程(AOP)框架来自动生成其中的一些,从而消除一些属性注入代码.
当你完成时,它可能看起来像这样:
[InjectedLogger]
public ILogger Logger { get; set; }
Run Code Online (Sandbox Code Playgroud)
您还可以使用他们的方法跟踪示例代码来自动跟踪方法入口和出口代码,这可能无需一起添加一些记录器属性.您可以在类级别或命名空间宽度应用该属性:
[Trace]
public class MyClass
{
// ...
}
// or
#if DEBUG
[assembly: Trace( AttributeTargetTypes = "MyNamespace.*",
AttributeTargetTypeAttributes = MulticastAttributes.Public,
AttributeTargetMemberAttributes = MulticastAttributes.Public )]
#endif
Run Code Online (Sandbox Code Playgroud)
sll*_*sll 23
好问题.我相信大多数项目记录器都是单身人士.
我想到了一些想法:
Object
类型,这样每一类将能够调用记录器的方法,例如LogInfo()
,LogDebug()
,LogError()
And*_*bel 14
单身是一个好主意.更好的想法是使用注册表模式,它可以更好地控制实例化.在我看来,单例模式太接近全局变量.通过注册表处理对象创建或重用,将来可以对实例化规则进行更改.
Registry本身可以是一个静态类,提供访问日志的简单语法:
Registry.Logger.Info("blabla");
Run Code Online (Sandbox Code Playgroud)
简单的单身人士不是一个好主意.这使得更换记录器变得困难.我倾向于为记录器使用过滤器(一些"嘈杂"类可能只记录警告/错误).
我使用单例模式结合记录器工厂的代理模式:
public class LogFactory
{
private static LogFactory _instance;
public static void Assign(LogFactory instance)
{
_instance = instance;
}
public static LogFactory Instance
{
get { _instance ?? (_instance = new LogFactory()); }
}
public virtual ILogger GetLogger<T>()
{
return new SystemDebugLogger();
}
}
Run Code Online (Sandbox Code Playgroud)
这允许我创建一个FilteringLogFactory
或只是SimpleFileLogFactory
不更改任何代码(因此遵守开放/封闭原则).
样品扩展
public class FilteredLogFactory : LogFactory
{
public override ILogger GetLogger<T>()
{
if (typeof(ITextParser).IsAssignableFrom(typeof(T)))
return new FilteredLogger(typeof(T));
return new FileLogger(@"C:\Logs\MyApp.log");
}
}
Run Code Online (Sandbox Code Playgroud)
并使用新工厂
// and to use the new log factory (somewhere early in the application):
LogFactory.Assign(new FilteredLogFactory());
Run Code Online (Sandbox Code Playgroud)
在您的课程中应该记录:
public class MyUserService : IUserService
{
ILogger _logger = LogFactory.Instance.GetLogger<MyUserService>();
public void SomeMethod()
{
_logger.Debug("Welcome world!");
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
27898 次 |
最近记录: |