2016-03-14 102 views
0

關於構造函數注入Unity的建議做法是什麼? 接下來的兩個例子是從DI的角度來看更好的做法嗎?有更好的解決方案嗎?Unity - 構造函數注入的依賴屬性或接口繼承

(這些例子都是簡單的插圖)

public interface ICircle 
{ 
     double Radius{get;set;} 
} 

Container.RegisterType<ICircle, SmallCircle>("Small"); 
Container.RegisterType<ICircle, BigCircle>("Big"); 

public class Bike{ 
    Public Bike([Dependency("Big") ICircle bigCircle, Dependency("Small") ICircle smallCircle) {  } 
} 

還是這個,更多的強類型的解決方案......

public interface IBigCircle : ICircle 
{ 
    // **Empty interface** 
} 

Container.RegisterType<ICircle, SmallCircle>(); 
Container.RegisterType<IBigCircle, BigCircle>(); 

public class Bike{ 
    Public Bike(IBigCircle bigCircle, ICircle smallCircle) {  } 
} 

我擔心的是空的接口,這個數字可以通過在時長第二個解決方案。

+0

第一種方法是不好的,因爲它讓你的類知道他們將接收哪些實現。第二種方法是嘗試解決這個問題。我建議你在有多個相同接口的實現時使用[Pure DI](http://blog.ploeh.dk/2014/06/10/pure-di/)。有關相關討論,請參見[本文](http://yacoubsoftware.blogspot.com/2015/08/why-di-containers-fail-with-complex.html)。 –

回答

0

IMO,第一碼樣本比第一更好,因爲它不弄亂不必要接口(例如IBigCircle)設計。但是,這兩個例子都不是很好。第一個示例的問題是使用DependencyAttribute將容器耦合到應用程序,這是應該避免的。

因此,如果這兩個例子不比什麼是更好的選擇更好?

這裏有一些。第一備選方案是使用一個InjectionFactory來實例化所需的對象:

IUnityContainer container = new UnityContainer(); 

container.RegisterType<ICircle, SmallCircle>("Small"); 
container.RegisterType<ICircle, BigCircle>("Big"); 

container.RegisterType<Bike>(new InjectionFactory(
    c => new Bike(c.Resolve<ICircle>("Big"), c.Resolve<ICircle>("Small")))); 

在上述例子中容器被用於解析「大」和「小」註冊ICircle實現。另外,因爲我們使用new Bike,所以我們得到構造函數參數的編譯時檢查。

另一個類似的方法是使用一個InjectionConstructor指定的對象注入:以上

container.RegisterType<Bike>(new InjectionConstructor(
    new ResolvedParameter<ICircle>("Big"), 
    new ResolvedParameter<ICircle>("Small") 
    )); 

告訴統一使用兩個ICircle參數的構造和ResolvedParameter指示來解析名稱的特定ICircle

您可以使用(但可能不會是第一選擇,但這裏包括了完整)另一種方法是在指定時間的決心,而不是註冊時需要什麼類型:

container.Resolve<Bike>(
    new ParameterOverride("bigCircle", container.Resolve<ICircle>("Big")), 
    new ParameterOverride("smallCircle", container.Resolve<ICircle>("Small"))); 
+1

這個使用InjectionConstructor的例子看起來比我寫的兩個例子更合適。我喜歡的是實現ICircle的類不會對Unity有任何依賴。他們甚至可以在一個沒有引用它的項目中。 – Zeljko

0

在第一種方法中,您的類將知道將被注入到其中的依賴項的名稱。所以這個代碼:

[Dependency("Big")] ICircle bigCircle 

是不是從很多不同:

bigCircle = ServiceLocator.Locate<ICircle>("Big"); 

這是service locator anti-pattern

你的類基本上是指導容器注入一個具有特定名稱的依賴關係。它涉及到構圖過程。在進行適當的依賴注入時,類只應具有被動角色。

你的第二種方法是試圖通過引入又一個代表相同抽象的接口來解決這個問題,以取悅容器。如果您有decoratorICircle會發生什麼情況,您是否需要爲IBigCircle創建類似的裝飾器?

更好的方法是在沒有容器的情況下執行依賴注入。這被稱爲Pure DI。有關相關討論,請參見this article。當您有多個單一接口的實現(在許多應用中都是如此)時,Pure DI特別有用。

+0

我明白了,我一般都同意。這兩個例子都不對。關於你關於裝飾者的問題,也許 - 是的。關於純粹的DI概念,我並不熟悉它。我會穿過它,我會在這裏寫下我的反饋。 – Zeljko

0

該示例帶有一些假設。例如,通過讀取接口名稱建議IBigCircle的半徑大於ISmallCircle,但取決於實現,而不取決於接口的名稱。接口不能保證他們的名字暗示什麼。 (就像IEnumerable<string> bigList, IEnumerable<string> smallList不能真正執行哪個更大。)

如果重要的是一個比另一個大,你可以只依賴兩個ICircles並在運行時確定哪個更大。或者你可以有一個由兩個ICircles組成的接口,並使用某種工廠來創建可接受的實現中可接受的圈對。

+0

您可以忽略接口名稱。我試圖看看在我有多個相同接口的實現時,哪種方法更適合於Unity DI。 – Zeljko