How to change dependency registration at run time using simple injector?

风流意气都作罢 提交于 2019-12-07 07:57:13

问题


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.


回答1:


In case IsRuntimeFlag is a configuration value (thus cannot change during the lifetime of the application), you can make the registration as follows:

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

or equally:

container.Register(typeof(I), IsRuntimeFlag ? typeof(A) : typeof(B));

In case the value can change during the lifetime of the application a proxy or composite that deals with dispatching to the right instance is the right solution:

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

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

    void I.Method() => this.Instance.Method();

    private I Instance => IsRuntimeFlag ? this.a : this.b;
}

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

container.Register<I, RuntimeFlagIComposite>();

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

container.Register<A>(Lifestyle.Singleton);
container.Register<B>(Lifestyle.Scoped);

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, RuntimeFlagIComposite>();

container.RegisterConditional<I, A>(c => c.Consumer.Target.Name == "a");
container.RegisterConditional<I, B>(c => c.Consumer.Target.Name == "b");


来源:https://stackoverflow.com/questions/12083919/how-to-change-dependency-registration-at-run-time-using-simple-injector

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!