RegisterWithContext和生活方式不匹配
本文关键字:不匹配 生活方式 RegisterWithContext | 更新日期: 2023-09-27 18:16:10
我想注入一个记录器到我的控制器,我需要将扩展信息传递给记录器的构造函数。为此,我使用了RegisterWithContext
:
container.RegisterWithContext<Common.Logging.ILogger>(context =>
{
if (context.ServiceType == null && !container.IsVerifying())
{
throw new InvalidOperationException(
"Can't request ILogger directly from container, " +
"it must be injected as a dependency.");
}
return new Common.Logging.NLogLogger(context.ImplementationType.FullName);
});
RegisterWithContext
扩展方法显式将提供的委托注册为Transient
。
我需要在一个碰巧是单例的服务中注入相同的Logger (Common.Logging.NLogLogger
)。
在升级到SimpleInjector 3.0.6之前,事情似乎如预期的那样工作,container.Verify()
对整个配置非常满意。
升级后校验器返回一些错误:
[Lifestyle Mismatch] SearchEngineIndexerService (Singleton)取决于ILogger实例(瞬态)。[生活方式不匹配]会员服务(Web请求)依赖于ILogger (Transient)。
,这是有意义的。我能理解为什么会发生这种情况,为什么应该避免。
我试图避免"我是否记录了太多"综合症,但是,实际上,我真的需要在几个服务中做一些记录。
我已经尝试使用RegisterConditional根据某些条件注册一个不同的记录器,但是,当然,现在所有的记录器都应该是有条件注册的,否则我会得到这个异常:
类型ILogger已被注册为无条件注册。对于非泛型类型,不能混合使用条件注册和无条件注册。
将一个记录器注册为控制器的暂态记录器,而将另一个记录器注册为单例服务的最佳方法是什么?
您现在看到这个异常的原因是v3.0.6修复了一些在某些情况下阻止生活方式不匹配警告显示的错误。
最好忽略RegisterWithContext
扩展方法,因为它在v3中已经被RegisterConditional
方法所取代。然而,RegisterConditional
只允许注册类型;不是委托,因为委托允许您基于运行时决策做出决策,但是在对象图解析期间做出运行时决策是不好的实践。
public sealed class Logger<T> : ILogger
{
private static readonly ILogger logger =
new Common.Logging.NLogLogger(typeof(T).FullName);
// Implement ILogger methods here
void ILogger.Log(string message) {
// Delegate to real logger
logger.Log(message);
}
}
这个实现可以注册如下:
container.RegisterConditional(typeof(ILogger),
c => typeof(Logger<>).MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
文档对此有更详细的描述。