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

戏子无情 提交于 2019-12-05 09:37:51

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