在answer之后我做了这个:
public class Log4netAdapter<T> : ILogger
{
private static readonly log4net.ILog logger = LogManager.GetLogger(typeof(T));
public void Log(LogEntry entry)
{
if(entry.LoggingEventType == LoggingEventType.Information)
logger.Info(entry.Message, entry.Exception);
else if(entry.LoggingEventType == LoggingEventType.Warning)
logger.Warn(entry.Message, entry.Exception);
else if(entry.LoggingEventType == LoggingEventType.Error)
logger.Error(entry.Message, entry.Exception);
else
logger.Fatal(entry.Message, entry.Exception);
}
}
然后在Simple Injector上:
container.RegisterConditional(
typeof(ILogger),
c => typeof(Log4netAdapter<>).MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
如果我在我需要的每个类构造函数上注入ILogger,这很有用。我的问题是我有一些类,我不能使用构造函数注入。对于这种情况,我会小心翼翼地做:
var logger = SimpleInjectorInitializer.Container.GetInstance<ILogger>();
但是上述方法不起作用,因为c.Consumer
为null
,它会在简单的注入类上引发错误。
以下是我需要解决ILogger
的示例之一,此类已在webapi启动类中注册。
public class ExceptionWebApiHandlingAttribute : IExceptionFilter
{
public ExceptionWebApiHandlingAttribute()
{
}
}
还有其他选择吗?
由于
答案 0 :(得分:2)
在处理应用程序边界时,有时很难或不可能使用构造函数注入。典型示例是MVC过滤器属性或需要默认构造函数的ASP.NET Web Form Page
类。
这些问题的典型解决方案是将此类边界类转换为Humble Object,其中所有有趣的逻辑都从边界类提取到组件中。边界类应仅包含对服务定位器的调用,并在已解析的服务上调用一个方法。这样可以最大限度地减少应用程序中不可测试代码的数量。
在所有其他情况下,应首选构造函数注入。
然而,你解决ILogger
的事实意味着你的边界类做得太多了。相反,此ILogger
应该是您从边界类提取的组件的构造函数依赖项,以成为一个简单对象。
一旦你完成了这项工作,你就不会再直接解决ILogger
这就解决了你的问题; ILogger
已成为消费者的依赖关系,这可确保Simple Injector能够代表您构建正确的Logger<T>
。
当涉及到将依赖关系应用于Web API中的异常过滤器(您的特定情况)时,一个好的解决方案是为您的异常过滤器创建一个代理,该代理将调用委托给要解析的实际过滤器。这可以是一些基础设施,并解释了这个概念here。
如果由于某种原因无法应用上述建议,您可以随时直接从容器中请求Logger<T>
:
ILogger log = SimpleInjectorInitializer.Container.GetInstance<Logger<MyHumbleObject>>();