6

我正在使用Simple Injector IoC 框架,我希望能够在运行时更改依赖项注册。例如,我有两个实现,AB,接口I。实现A是在应用程序启动时注册的,但是根据一些在运行时可能会改变的标志,我想切换实现。我们目前正在执行我们的OnActionExecuting事件,我们BaseController所有的控制器都继承自该事件。这是我正在尝试做的示例代码。

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);
}

在此先感谢您的帮助。

4

1 回答 1

11

如果IsRuntimeFlag是配置值(因此在应用程序的生命周期内不能更改),您可以按如下方式进行注册:

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

或同样:

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

如果值可以在应用程序的生命周期内发生变化,那么处理分派到正确实例的代理或组合是正确的解决方案:

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;
}

因为复合直接依赖于Aand B,所以可以简单的注册如下:

container.Register<I, RuntimeFlagIComposite>();

// Register A and B with their required lifestyles
container.Register<A>(Lifestyle.Singleton);
container.Register<B>(Lifestyle.Transient);

您还可以让您的组合依赖于I抽象本身而不是具体AB实现:

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

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

依赖于I抽象使得这个类更灵活,更可测试。但是,这确实意味着您需要注册它有点不同。这可以使用RegisterConditional. 这是一个例子:

container.Register<I, RuntimeFlagIComposite>();

container.RegisterConditional<I, A>(c => c.Consumer.Target.Name == "a");
container.RegisterConditional<I, B>(c => c.Consumer.Target.Name == "b");
于 2012-08-23T05:56:43.137 回答