2011-11-18 70 views
10

我的目標是構造函數注入一個實現接口的對象數組。使用Unity注入數組

以下是我目前擁有它的方式。

  Container 

        .RegisterInstance<Company>(ParseCompany(args[1]) 

        .RegisterInstance<eTargets>(ParseTargets(args[2])) 

        .RegisterInstance<ILoader[]>(new ILoader[] { 
         Container.Resolve<CustomerLoader>(), 
         Container.Resolve<PaymentLoader(), 
         Container.Resolve<InvoiceLoader() 
        }); 

這是通常在容器配置中調用Resolve還是有一種更標準的方法來完成同樣的事情?

回答

25

Unity 原生理解數組,所以沒有理由讓它變得如此複雜。只需註冊您想要包含的ILoaders並正常解析對象圖。 自動佈線將完成剩下的工作:

container.RegisterType<ILoader, FooLoader>("foo"); 
container.RegisterType<ILoader, BarLoader>("bar"); 
container.RegisterType<ILoader, BazLoader>("baz"); 

var c = container.Resolve<MyConsumer>(); 

假設MyConsumer構造是這樣定義的:

public MyConsumer(ILoader[] loaders) 

但是,你應該知道,(對於一些深不可測的原因)團結只包含這種方式命名爲組件。該默認組件:

container.RegisterType<ILoader, Loader>(); 

包括在陣列中,因爲它沒有名字。

+0

哇,這是一個偉大的小費感謝 –

+0

不完全是深不可測的:原因是,如果你需要爲同類型的多個條目,則必須添加一個名稱,否則團結會認爲你實際上覆蓋以前的條目(這是禁止的)。 –

+3

@BrunoBrant'深不可測',因爲沒有其他的DI容器是這樣工作的。見例如[我的書](http://amzn.to/12p90MG)瞭解更多詳情。 –

3

在「配置時間」期間使用Resolve是可以接受的,並且通常很有用,它對於數組或枚舉數據非常有效。

您也可以通過註冊ILoader[]類型並使用帶名稱的RegisterType重載註冊每個特定的ILoader類型來完成上述操作。

然後,無論何處需要ILoader[](例如需要注入),以上所有內容都將在配置時間後解決。當然,如果您需要多個/不同的ILoader[]它會回到在配置期間需要使用Resolve

1

如果您有一個稍微複雜一些的場景,需要在不同的地方使用不同的數組值,那麼您可以使用ResolvedArrayParameter,例如,

container.RegisterType<ILoader, FooLoader>("foo"); 
container.RegisterType<ILoader, BarLoader>("bar"); 
container.RegisterType<ILoader, BazLoader>("baz"); 
container.RegisterType<ILoader, BooLoader>("boo"); 

container.RegisterType<IConsumer, MyConsumer>("c1", 
    new InjectionConstructor(
     new ResolvedArrayParameter<ILoader>(
      new ResolvedParameter<ILoader>("foo"), 
      new ResolvedParameter<ILoader>("bar")))); 

container.RegisterType<IConsumer, MyConsumer>("c2", 
    new InjectionConstructor(
     new ResolvedArrayParameter<ILoader>(
      new ResolvedParameter<ILoader>("baz"), 
      new ResolvedParameter<ILoader>("boo")))); 

var c1 = container.Resolve<MyConsumer>("c1"); 
var c1 = container.Resolve<MyConsumer>("c2");