2012-08-23 39 views
5

我正在使用Simple Injector IoC框架,我希望能夠在運行時更改依賴項註冊。例如,我有兩個實現,AB,接口爲I。實現A是在應用程序啓動時註冊的,但根據某些可在運行時更改的標誌,我希望切換實現。我們目前正在執行我們的BaseControllerOnActionExecuting事件,這是我們所有控制器繼承的事件。這是我正在嘗試做的示例代碼。如何使用簡單注入器在運行時更改依賴註冊?

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

在此先感謝您的幫助。

+1

我建議結合工廠和戰略模式,而不是使用DI容器爲此。儘早使用Container來解析對象圖。參見[Composition Root](http://blog.ploeh.dk/2011/07/28/CompositionRoot.aspx)。 – TrueWill

+0

您是否需要手動執行此操作?使用IOC容器框架怎麼樣? –

回答

9

萬一IsRuntimeFlag是一個配置值(因此該應用程序的生命週期內不能改變),就可以使登記如下:

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

或同等:

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

萬一該值可以在應用程序的生命週期期間更改代理或composite,處理調度到正確的實例是正確的解決方案:

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

由於複合直接取決於AB,可以簡單地如下進行註冊:

container.Register<I, RuntimeFlagIComposite>(); 

AB具有不同的壽命比瞬態(每個請求一個新的實例),則也應該註冊它們。例如:

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

你也可以讓你的組合取決於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抽象使得這個類更靈活,更測試。然而,它的意思是,你需要註冊一點點不同:

container.Register<I, RuntimeFlagIComposite>(); 

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

謝謝您的回答,但是,此標誌在容器註冊時是未知的,並且可以在應用程序的整個生命週期中進行更改。我想我可以設置一個全局標誌並在應用程序的後期更改,但我認爲這不是一個乾淨的方法。仔細一看,我確實認爲複合模式可能適用於這種情況。再次感謝你的幫助。 – Will

+0

嗨史蒂文, 只是想知道如果你有任何其他的想法。試圖實現這一點,我意識到該標誌還取決於Web應用程序層中的東西,特別是cookie值,而不是服務層,這是複合材料所在的位置。因此,該組合將無法訪問該標誌。再次提前感謝。 – Will

+1

我想你回答了你自己的問題。如果組合將取決於UI特定的事情,它應該在UI層中定義。由於界面是在較低層定義的,因此在您的UI層中定義界面絕對沒問題(或者您甚至可以將它作爲您的組合根的一部分)。 – Steven