Bal*_*ldy 4 dependency-injection nlog autofac
继这个问题后,我希望autofac将声明对象的类型注入到我的NLog服务的构造函数中,以便它可以正确记录哪个类型是日志记录条目.
我的NLogService类看起来像这样......
public class NLogService : ILogService
{
private readonly Logger _logger;
public NLogService(Type t)
{
var consumerType = t.DeclaringType.FullName;
_logger = LogManager.GetLogger(consumerType);
}
Run Code Online (Sandbox Code Playgroud)
然而它在应用程序启动时失败,因为它显然无法解决注入NLogService的构造函数的内容,并出现以下错误...
可以使用可用的服务和参数调用在'MyProduct.Domain.Services.Logging.NLogService'类型上找到'公共绑定标志'的构造函数:无法解析构造函数'Void .ctor'的参数'System.Type t'(系统类型)'.
所以,我的问题是 - 如何指示autofac注入调用类的类型?
我试过这个......
public NLogService(Type t)
{
var method = MethodBase.GetCurrentMethod();
Type consumingType = method.DeclaringType;
var consumerType = consumingType.FullName;
var consumerType = t.DeclaringType.FullName;
_logger = LogManager.GetLogger(consumerType);
}
Run Code Online (Sandbox Code Playgroud)
但我最终还是结束了 MyProduct.Domain.Services.Logging.NLogService
我想要的是进行实际日志记录的类的类型.
我已经尝试过这个建议,它对我也没有用.
可以使你的NLogService通用,即NLogService<T>使用Autofac的开放式泛型支持吗?
然后你可以这样做:
public class NLogService<T> : ILogger<T>
{
private readonly Logger _logger;
public NLogService()
{
_logger = LogManager.GetLogger(typeof(T).FullName);
}
}
Run Code Online (Sandbox Code Playgroud)
使用Autofac没有真正好的方法,因为不支持"基于上下文的注入"(这是你要做的).有一个解决方法,但它不是很好......
您可以做的是恢复属性注入并为该ILogService属性定义基类或接口.例如,您可以定义以下界面:
public interface ILoggerContainer
{
public ILogService Logger { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以在需要记录器的所有类型上实现此接口:
public class Consumer : IConsumer, ILoggerContainer
{
public ILogService Logger { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
有了这个,您可以按如下方式配置Autofac:
builder.RegisterType<ILoggerContainer>()
.OnActivating(e =>
{
var type = typeof(LogService<>)
.MakeGenericType(e.Instance.GetType());
e.Instance.Logger = e.Context.Resolve(type);
});
Run Code Online (Sandbox Code Playgroud)
您可能会发现更清洁的另一种解决方法是注入ILogger<T>与父类型的类型相同的类型:
public class Consumer : IConsumer
{
public Consumer(ILogger<Consumer> logger) { }
}
Run Code Online (Sandbox Code Playgroud)
这使得配置更容易,并且使您不必拥有基类.哪一个最合适取决于你.
正如我所说,这些是变通方法,但说实话,您可能需要重新考虑应用程序中的日志记录策略.也许你在很多地方登录.在我写的应用程序中,几乎不需要记录,当我这样做时,我会编写一个足够表达的日志消息,这样就不需要传达触发事件的类型.当您记录异常时,您将始终拥有完整的堆栈跟踪(异常记录几乎只发生在应用程序的外层,而不是在服务中).