使用Simple Injector我在记录器中遇到了一个共同的主题,我在记录器注入的服务对象的构造函数中设置了记录器名称。当服务写入日志时,可以通过此日志名轻松识别它。
由于将为每项服务设置LogNames
,因此每个对象图形请求的记录器应该是唯一的。
我想在构建图表时自动执行此操作,我已经在ExpressionBuilt()
中进行了调查但是我正在努力并且尚未得到我想要工作的东西 - 这是否可能(或者是可以的)想做什么??
我的构造函数代码如下(这个LogName
属性设置代码在我的大多数服务中都很常见。)
谢谢,
克里斯
public interface ILogger
{
void LogMessage(string message, LogLevel level,
ILoggableCompany company = null);
string LogName {get; set; }
}
public BusinessUnitService
{
private readonly IUnitOfWork unitOfWork;
private readonly ILogger logger;
public BusinessUnitService(IUnitOfWork unitOfWork,
ILogger logger)
{
this.unitOfWork = unitOfWork;
this.logger = logger;
// it would be great if we could take away this
// line and set it automatically
this.logger.LogName = this.GetType().ToString();
}
}
答案 0 :(得分:1)
此设计看起来有点像log4net的Logger<T>
设计,其中T
将是为其创建记录器的类。虽然我无法调查你的设计,但我想知道:aren't you logging too much?
如果您确实需要这样做,请至少从LogName
界面删除ILogger
属性,因为它在那里没有业务。这意味着您必须从构造函数中删除设置此属性的代码,这绝对没问题,因为这是整个地方的代码重复。
您要做的是基于上下文的注入,这不是开箱即用的,但Simple Injector wiki包含一个Context Bases Injection section,解释了如何添加此支持。此文档页面甚至使用Logger<T>
作为示例: - )
使用wiki所指的the extension method,您可以执行以下操作:
public interface ILogger
{
void LogMessage(string message, LogLevel level,
ILoggableCompany company = null);
// No LogName property here. Keep it clean.
}
public class LoggerImpl : ILogger
{
public void LogMessage(string message,
LogLevel level, ILoggableCompany company)
{
// implementation
}
// Property only part of the implementation.
public string LogName {get; set; }
}
// The parent contains information about the type in
// which ILogger is injected.
container.RegisterWithContext<ILogger>(parent =>
{
// Retrieve a new LoggerImpl instance from the container
// to allow this type to be auto-wired.
var logger = container.GetInstance<LoggerImpl>();
// ImplementationType is null when ILogger is
// requested directly (using GetInstance<ILogger>())
// since it will have no parent in that case.
if (parent.ImplementationType != null)
{
// Set the LogName with the name of the class
// it is injected into.
logger.LogName = parent.ImplementationType.Name;
}
return logger;
});
// Register the LoggerImpl as transient. This line is
// in fact redundant in Simple Injector, but it is important
// to not accidentally register this type with another
// lifestyle, since the previous registration depends on it
// to be transient.
container.Register<LoggerImpl>();
因为这可以通过挂钩到BuiltExpression
事件,并通过重新连接表达式来解决实例,所以这几乎与使用Func<T>
工厂方法的注册一样快。