2

我試圖打開我的腦海花式的IoC原則,我碰到的文章來的IoC的好處: Martin fowler on IoC廠VS PicoContainer的 - 集裝箱

他提供了使用PicoContainer的的一些例子:

private MutablePicoContainer configureContainer() { 
     MutablePicoContainer pico = new DefaultPicoContainer(); 
     Parameter[] finderParams = {new ConstantParameter("movies1.txt")}; 
     pico.registerComponentImplementation(MovieFinder.class, ColonMovieFinder.class, finderParams); 
     pico.registerComponentImplementation(MovieLister.class); 
     return pico; 
    } 

然後樣品用量:

public void testWithPico() { 
     MutablePicoContainer pico = configureContainer(); 
     MovieLister lister = (MovieLister) pico.getComponentInstance(MovieLister.class); 
     Movie[] movies = lister.moviesDirectedBy("Sergio Leone"); 
     assertEquals("Once Upon a Time in the West", movies[0].getTitle()); 
    } 

首先想到的是,爲什麼要使用像PicoContainer這樣複雜的東西來配置對象的創建 - 實際上應用依賴注入 - (我是.NET開發人員,所以在.NET中它可能需要使用反射,這是耗時),當我們可以實現相同封裝的對象創建(例如)工廠建設者,與快速運算符。

另一件事:configureContainer()仍然被編譯,確切的類型是在編譯時指定的。那麼爲什麼不使用工廠,並在配置文件中決定使用哪個工廠?

由於我剛剛接觸這種方法,我想我在IoC容器的好處方面缺少一些東西。

回答

1

我剛更新了一個與這個問題相關的答案here

在.net中,我會看看圍繞Unity Framework(來自MSFT)的文檔。我還對編寫實施註冊的想法持懷疑態度,但隨着時間的推移,我克服了這一點。主要是因爲你確實可以使用基於文件的配置,你可以註冊多個實現(並且標記每個實現以便它們可以被調用),並且通常你在生產中不使用多個實現。

最大的好處是自動裝配 - 您的依賴關係爲您找到。一組複雜的類的鏈式自動裝配非常漂亮,如果沒有其他因爲你可以輕鬆地註冊一個10類中的一個類的Mock實例而不觸及實現代碼。這導致了以引導容器爲代價的大量可測試性。現在對我來說,這是桌面賭注,甚至不值得討論。想象一下,如果Type1依賴於2,3和4,4依賴於5和6,6依賴於7.如果我想測試系統如何對6中的錯誤做出反應,我該怎麼做?我需要做的就是Mock(使用像Moq這樣的酷酷框架)Type6,註冊模擬,但使用其他類的實際實現。

[Fact] 
public void TestType6BlowingUp() 
{ 
    IocContainer container = new IocContainer(); 
    container.RegisterType(Type1, Type1Impl); 
    container.RegisterType(Type2, Type2Impl); 
    container.RegisterType(Type3, Type3Impl); 
    container.RegisterType(Type4, Type4Impl); 
    container.RegisterType(Type5, Type5Impl); 
    container.RegisterType(Type6, Type6Mock); 
    container.RegisterType(Type7, Type7Impl); 

    Type1 type1 = container.Resolve<Type1>(); 
    Type1Response response = type1.DoSomethingThatCallsType6Downstream(); 
    //Should get errorcode 500 
    Assert.True("Expected ErrorCode 500", response.ErrorCode == 500); 
}