2012-09-18 33 views
0

隨着StructureMap,可以一個約定注入基於其名稱的情況下,像這樣:能否根據慣例注入一個名爲ctor arg的名稱實例?

構造函數:

public HomeController(IQuery getItemByProductNumberQuery, IQuery getCustomerById) 

StructureMap配置:

x.For<IQuery>().Add<GetItemByProductNumberQuery>().Named("getItemByProductNumberQuery"); 
x.For<IQuery>().Add<GetCustomerById>().Named("getCustomerById"); 

我與遺留代碼一起工作,所以更換DI容器是一項艱鉅的任務,但瞭解其他容器解決手頭問題的方法也很有意思。

回答

2

在我看來,你在代碼庫中缺少抽象。在正常情況下,服務(您的案例中的IQuery)應該是明確的,您的情況並非如此。通過參數名識別它們往往容易出錯,並導致難以維護的DI配置。這並不總是必須這樣(可以在this example中看到),但它可能是你的情況。

爲了解決這個問題,讓你的IQuery接口通用:

public interface IQuery<TParameters, TResult> 
{ 
    TResult Handle(TParameters parameters); 
} 

這允許您通過其關閉通用表示註冊此接口的所有實現,並允許您控制依靠這個封閉的通用表示:

public HomeController(
    IQuery<GetItemByProductNumberParameters, Item> getItemQuery, 
    IQuery<GetCustomerByIdParameters, Customer> getCustomerById) 

正如你所看到的,每個查詢定義了一個'XXXParameters'對象。這是一個包含運行查詢所需參數的DTO。在HomeController的代碼可能是這樣的:

public View Item(int productNumber) 
{ 
    var parameters = new GetItemByProductNumberParameters 
    { 
     ProductNumber = productNumber, 
     // other parameters here 
    }; 

    Item item = this.getItemQuery.Handle(parameters); 

    return this.View(item); 
} 

這可能是一個有點難以批量一氣呵成用StructureMap,但this SO question might help註冊所有IQuery<TParameter, TResult>實現。如果不是,使用另一個DI容器可能會產生更好的結果。

您可以在本文中以這種方式查找有關爲什麼要對查詢進行建模的更多信息:Meanwhile… on the query side of my architecture