从没有" GetInstance"的简单注入器获取实例方法

时间:2017-03-08 12:08:31

标签: c# log4net simple-injector

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.Consumernull,它会在简单的注入类上引发错误。

以下是我需要解决ILogger的示例之一,此类已在webapi启动类中注册。

public class ExceptionWebApiHandlingAttribute : IExceptionFilter
{
    public ExceptionWebApiHandlingAttribute()
    {
    }   
}

还有其他选择吗?

由于

1 个答案:

答案 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>>();