如何使用简单的注射器上改变依赖登记在运行时? [英] How to change dependency registration at run time using simple injector?

查看:147
本文介绍了如何使用简单的注射器上改变依赖登记在运行时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用href="http://simpleinjector.$c$cplex.com" rel="nofollow">简单的注射器 IoC框架的 A 和 B ,接口。实施 A 被记录在应用程序启动,但根据一些标志,它可以在运行时改变,我想切换的实现。我们现在正在做的这个 OnActionExecuting 事件我们 BaseController ,其中我们所有的控制器,从继承。这里是什么,我试图做样品code。

I'm using the Simple Injector IoC framework, and I would like to be able to change the dependency registration at run time. For example, I have two implementations, A and B, of interface I. Implementation A is registered at app start, but depending on some flag which can change during runtime, I would like to switch the implementation. We are currently doing this the OnActionExecuting event of our BaseController, which all of our controllers inherit from. Here is the sample code of what I am trying to do.

protected override void OnActionExecuting(
    ActionExecutingContext filterContext)
{
    if (IsRuntimeFlag)
    {
        // check current implementation type and 
        // change implementation to A
    }
    else
    {
        // check current implementation type and 
        // change implementation to B
    }

    base.OnActionExecuting(filterContext);
}

在此先感谢您的帮助。

Thanks in advance for your help.

推荐答案

您可以注册一个工厂委托是这样的:

You can either register a factory delegate like this:

container.Register<I>(() =>
{
    if (IsRuntimeFlag)
    {
        return container.GetInstance<A>();
    }
    else
    {
        return container.GetInstance<B>();
    }
});

然而,当这种 IsRuntimeFlag 是一个配置值(这样可以在应用程序的生命周期内没有改变),最好是进行如下注册:

However, when this IsRuntimeFlag is a configuration value (thus cannot change during the lifetime of the application), it is better to register it as follows:

if (IsRuntimeFlag)
{
    container.Register<I, A>();
}
else
{
    container.Register<I, B>();
}

这使注册更具有确定性,它允许您验证容器有更多的确定性。

This makes the registration more deterministic, which allows you to validate the container with more certainty.

也可以创建一个复合与调度到正确的实例涉及:

Or you can create a composite that deals with dispatching to the right instance:

public class RuntimeFlagIComposite : I
{
    private A a;
    private B b;

    public RuntimeFlagIComposite(A a, B b)
    {
        this.a = a;
        this.b = b;
    }

    void I.Method()
    {
        var instance = IsRuntimeFlag ? this.a : this.b;
        instance.Method();
    }
}

由于复合材料直接取决于 A B ,你可以简单地注册,如下所示:

Because the composite directly depends on A and B, you can simply register it as follows:

container.Register<I, RuntimeFlagIComposite>();

A B 有不同的寿命暂时性的(每个请求一个新的实例),你应该还注册。例如:

When A or B have a different lifetime than transient (a new instance for each request), you should also register them. For instance:

container.RegisterSingle<A>();
container.RegisterPerWebRequest<B>();

您也可以让你的组合取决于抽象本身,而不是具体的 A B 实现:

You can also let your composite depend on the I abstraction itself instead of the concrete A and B implementations:

public class RuntimeFlagIComposite : I
{
    private I a;
    private I b;

    public RuntimeFlagIComposite(I a, I b)
    {
        this.a = a;
        this.b = b;
    }
}

根据抽象使得这个类更灵活,更容易测试。但它确实意味着,你需要注册它一点点不同:

Depending on the I abstraction makes this class more flexible and more testable. It does mean however, that you need to register it a little bit different:

container.Register<I>(() => new RuntimeFlagIComposite(
        container.GetInstance<A>(),
        container.GetInstance<B>())
);

通常注册一个简单的代表(作为首次登记显示)往往是不够的,但创建一个单独的类型可以有利于在某些情况下。

Often registering a simple delegate (as the first registration showed) is often enough, but creating a separate type can be beneficial in some situations.

其实,这是一个可以可以适用于(几乎)所有的DI框架一种普遍现象。

In fact, this is a general pattern that can can apply to (almost) every DI framework.

这篇关于如何使用简单的注射器上改变依赖登记在运行时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆