基于生活方式simpleinjector注册实现

时间:2016-11-02 14:09:44

标签: c# dependency-injection simple-injector

我使用Simple Injector作为我的IoC容器。我想根据执行范围的存在注入我的类记录器。应该有一个默认记录器(单例)和其他基于我的上下文。

我尝试过这样的事情:

container.RegisterConditional(typeof(ILogger),
    x => typeof(NContextLogger<>).MakeGenericType(x.Consumer.ImplementationType),
    Lifestyle.Scoped,
    x => container.GetCurrentExecutionContextScope() != null);

container.RegisterConditional(typeof(ILogger),
    x => typeof(NLogger<>).MakeGenericType(x.Consumer.ImplementationType),
    Lifestyle.Singleton,
    x => container.GetCurrentExecutionContextScope() == null);

问题在于创建NContextLogger<>的任何实例。因为当它创建单身的NLogger<>时,simpleinjector不会尝试创建NContextLogger的实例。

1 个答案:

答案 0 :(得分:2)

提供给RegisterConditional的谓词不能用于运行时决策,因为谓词的结果被缓存并刻录到表达式树和已编译的委托中。然而, GetCurrentExecutionContextScope() Lifestyle.Scoped.GetCurrentScope(Container)的可用性是运行时决定。

在构造对象图时,不应该根据运行时条件做出决定(出于与runtime data shouldn't be injected into components相同的原因)。

不是在构建对象图的过程中根据运行时条件做出决策,而是应该推迟这些决策,直到构建对象图之后。最明显的方法是引入代理类:

public sealed class ProxyLogger<T> : ILogger
{
    private readonly Container container;

    public ProxyLogger(Container container) {
        this.container = container;
    }

    // Implement ILogger method(s)
    public void Log(string message) => Logger.Log(message);

    private ILogger Logger => Lifestyle.Scoped.GetCurrentScope(container) == null
        ? container.GetInstance<NLogger<T>>()
        : container.GetInstance<NContextLogger<T>>();
}

使用此代理类,您可以进行以下注册以满足您的要求:

container.RegisterConditional(typeof(ILogger),
    c => typeof(ProxyLogger<>).MakeGenericType(x.Consumer.ImplementationType),
    Lifestyle.Singleton,
    c => true);

container.Register(typeof(NLogger<>), typeof(NLogger<>), Lifestyle.Singleton);
container.Register(typeof(NContextLogger<>), typeof(NContextLogger<>),Lifestyle.Singleton);
相关问题