2014-04-04 72 views
1

我有一個需要依賴注入的類。由於該類已經是另一個抽象的實現,並且它的「兄弟」實現可能不共享相同的依賴關係,所以我嘗試使用屬性注入而不是構造函數注入。使用Unity做屬性依賴注入的正確方法

(所有這些類/接口名稱僅僅是用於說明目的)

IProvider抽象:

public interface IProvider 
{ 
    void ProviderMethod(); 
} 

IProvider實施(與IData的依賴我要注入)

public class ProviderClass : IProvider 
{ 
    // How do I inject this dependency? 
    [Dependency] 
    public IData data { get; set; } 

    public void ProviderMethod() 
    { 
     // Can't do this as data == null! 
     data.DataMethod(); 
    } 
} 

另一個IProvider實現(例如,以表明它不具有相同的依賴):

public class AnotherProviderClass : IProvider 
{ 
    // No data dependency here!! 

    public void ProviderMethod() 
    { 
     // Do other stuff here 
    } 
} 

IData的抽象和實施:

public interface IData 
{ 
    void DataMethod(); 
} 

public class DataClass : IData 
{ 
    public void DataMethod(); 
} 

我需要知道什麼是:如何使用Unity(我選擇的IOC容器)成功將物業依賴關係(IData)注入ProviderClass

我嘗試過所有的Unity註冊選項(RegisterType,RegisterInstance,Resolve ...)但注入的屬性總是以NULL結尾。我想這樣做,而不是隻是強制隨機代碼,直到它能夠工作。

還是有更好的方法注入(可選)依賴到'兄弟'類?

順便說一句,我最初的IProvider實現通過一個抽象工廠創建的,所以也許這可能是另一個領域,我應該關注這個IData的依賴關係(?)

+1

我不清楚爲什麼你不做構造函數注入。你能詳細說明一下嗎? – Steven

+0

主要是因爲依賴項是可選的,其他IProvider實現可能有許多自己的依賴項,這些依賴項對於它們的類是唯一的。 IProvider實現從抽象工廠返回(比如IProviderFactory);隨着每個新的IProvider實現的添加,工廠將不得不在其自己的注入策略(潛在的構造函數參數膨脹?)中適應越來越多的這些實現。 –

+0

使用Unity進行屬性依賴注入的正確方法是:讓已解析的類型包含正確的配置,不要重複自己。例如,如果您需要交叉切割問題將日誌記錄注入多個對象,則可以使用Interceptor。 – Programmer

回答

4

您仍然應該使用構造函數注入,因爲dependencies should hardly ever be optional

您試圖阻止IProviderFactory實施中的constructor over-injection,並且您可能不希望將容器注入工廠,以防止進入Service Locator anti-pattern

如果您在Composition Root的內部定義了IProviderFactory實施,那麼即使您注入容器,也會阻止自己執行服務定位器,因爲Service Locator is not about mechanics

所以,你應該定義你的ProviderFactory實現儘可能靠近你的統一配置越好,它應該是這個樣子:

public class ProviderFactory : IProviderFactory 
{ 
    private readonly Dictionary<string, Type> providerTypes; 
    private readonly Container container; 

    public ProviderFactory(Dictionary<string, Type> providerTypes, 
     Container container) { 
     this.providerTypes = providerTypes; 
     this.container = container; 
    } 

    public IProvider CreateProvider(string name) { 
     return (IProvider)this.container.Resolve(this.providerTypes[name]); 
    } 
} 

此實現可以註冊爲在Unity單。這使您無需將構造函數過度注入工廠,同時遠離服務定位器。