2014-09-04 150 views
4

雖然學習統一(在C#DI框架),我遇到其中一個類有ClassB的統一解決循環依賴

class ClassA : IClassA 
{ 
... 
    [Dependency] 
    public IClassB ClassB 
    { 
     get { return _classB; } 
     set 
     { 
      if (value == null) throw new ArgumentNullException("value"); 
      _classB = value; 
     } 
    } 

的setter和其他具有的ClassA的

一個構造函數注入的情況來
class ClassB : IClassB 
{ 
... 
    [InjectionConstructor] 
    public ClassB(IClassA classA) 
    { 
     _classA = classA; 
    } 
} 

我無法在容器中正確解析兩個類。

 var container = new UnityContainer(); 
     container.RegisterType<IClassB, ClassB>(); 
     container.RegisterType<IClassA, ClassA>(); 
     IClassA classA = new ClassA(); 
     var instance = container.Resolve<ClassA>(); 
     instance.DoSomethingFromClassB(); 

     log.Info("Constructor Injection"); 
     var instanceB = container.Resolve<ClassB>(); 
     instanceB.DoSomethingFromClassA(); 

這給了我一個堆棧溢出異常

我試圖解決這個不同的排序,但它似乎沒有工作。

我這個可行或我只是在浪費我的時間。這裏究竟發生了什麼。

回答

9

DI框架像Unity一樣工作的方式是,當您調用它們來實例化一個類時,它們遞歸地實例化所有傳遞給該類的構造函數(或由屬性設置)的類。這些類遵循相同的功能,所以你可以看到你是如何創建一個無限循環的遞歸。如果Unity在A需要B和B時如何構造A?也不能構建。

在大多數DI框架中,您無法解決共依賴類。 這是一個糟糕的設計模式和一個代碼味道。從傳統意義上講,如果ClassA需要知道約ClassBClassB作爲回報需要知道約ClassA,那麼現實是他們有共同的關注,應該合併成一個類ClassC。由於在這種情況下不存在問題的分離,你可以通過讓他們分成兩個班級而獲益。

例如Unity等DI用於促進控制反轉的模式,該模式僅在類具有單向依賴性(不需要彼此瞭解)時起作用。

+0

感謝..我想我明白了,我可以解決這兩個A和B C. – jtkSource 2014-09-04 15:57:41

+0

是的,你可以有ç決心A和B.這是一個常見的模式,以及 - 有擁有兩個相關類的「容器」或「作曲家」。不要太注意流行語/專業術語。 ;) – Haney 2014-09-04 16:00:54

9

我@Haney同意這是一個代碼味道,但它在技術上是可能的...

只要改變引用的類型之一,通過Lazy<T>得到解決。然後它實際上不會解析該類型,直到它被使用,這將會跳出無限遞歸循環。

class ClassB : IClassB 
{ 
... 
    [InjectionConstructor] 
    public ClassB(Lazy<IClassA> classA) 
    { 
     _classA = classA; 
    } 
} 
+0

謝謝。我們正在重構使用構造函數注入,它揭示了一些循環依賴關係。我們最終將其作爲臨時解決方案使用,以便我們可以檢查我們所擁有的內容,並將循環依賴項作爲一項單獨的任務清理。 – kevinpo 2016-03-02 16:50:09