2011-11-18 71 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");