2015-10-18 80 views
0

我可以在層次結構中使用DI容器創建新對象嗎?爲每個DI容器設置依賴關係,然後按類型聲明getInstance,並正確創建實例。另外,你可以閱讀很多文章,解釋DI容器應該位於主函數的層次結構的頂部,它不應該被傳遞或單獨傳遞。但是如果我想從容器中的實例從對象的層次結構中下來呢?我可以在層次結構中使用DI容器嗎?

+0

請提供一些僞代碼。它很難理解你的意思是什麼樣的層次結構:call,object,type,context? – Basilevs

+0

*我可以在層次結構中使用DI容器嗎?*您可以,但[您不應該](http://stackoverflow.com/a/2386636/126014)。 –

+0

*如果我想從容器中的實例從對象的層次結構中獲取實例?*爲什麼要這麼做?什麼是用例? –

回答

1

避免讓應用程序代碼(啓動代碼除外)直接依賴容器或對容器的抽象;這是一種反模式,稱爲Service Locator。啓動代碼通常被稱爲Composition Root

組合根是在您的應用程序中單獨的。該層位於其他層之上,例如表示層和業務層。

但這並不意味着您不能使用容器在某種情況之後以懶惰的方式創建對象圖的某些部分。這裏有一個例子:

// Defined in a shared library of your application, accessible to all other 
// code in your application. 
public interface ICommandProcessor 
{ 
    public void Process(object command); 
} 

這個接口的可能的用法如下:

this.commandProcessor.Process(new ShipOrderCommand(orderId)); 

雖然抽象並沒有注意一下使用的可能容器的話,這個抽象的實現仍可以取決於一個。但是由於應用程序代碼不應該依賴容器,因此應該在Composition Root(應用程序的啓動路徑)中定義此實現。這允許應用程序保持對這種工具的存在的遺忘,而容器仍然可以用於解析對象圖。下面是一個示例實現:

public class CommandProcessor : ICommandProcessor 
{ 
    private readonly Container container; 
    public CommandProcessor(Container container) { 
     this.container = container; 
    } 
    public void Process(object command) { 
     Type handlerType = typeof(ICommandHandler<>).MakeGenericType(command.GetType()); 
     dynamic handler = this.container.GetInstance(handlerType); 
     handler.Handle((dynamic)command); 
    } 
} 

所以長話短說,你可以使用容器延遲的方式創建對象圖,只要在你的應用程序,使用集裝箱的唯一層是構圖的根。

+0

你說的**應用程序代碼本身不必調用GetInstance **?如何定義應用程序代碼,以及爲什麼'CommandProcessor'類的Process'方法不被視爲應用程序代碼? – Narek

+0

@Narek:雖然Composition Root是您爲應用程序編寫的代碼的patt,但我們認爲它有點不同,並經常談論Composition Root與其他應用程序。雖然CR可能取決於Container,但您的應用程序的其餘部分可能不會。 – Steven

+0

聽起來像'Process'方法**是應用程序的其餘部分**,對不對?所以看起來,你說應用程序代碼不應該使用,但是你在應用程序代碼中使用它。 – Narek