2011-11-18 19 views
10

Il mio obiettivo è il costruttore di iniettare una matrice di oggetti che implementano un'interfaccia.Iniezione di array con Unity

Quanto segue è il modo in cui attualmente lo ho.

  Container 

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

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

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

è tipico di chiamare Resolve in configurazione del contenitore così o c'è un modo più standard per ottenere la stessa cosa?

risposta

25

Unity in modo nativo comprende le matrici, quindi non c'è motivo di renderlo così complicato. Basta registrare lo ILoaders per includere e risolvere normalmente i grafici degli oggetti. Auto-wiring si prenderà cura di tutto il resto:

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

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

supponendo che il costruttore MyConsumer è definita in questo modo:

public MyConsumer(ILoader[] loaders) 

Tuttavia, si deve essere consapevoli che (per qualche ragione insondabile) Unità include solo denominati componenti in questo modo. Il predefinito componente:

container.RegisterType<ILoader, Loader>(); 

sarà non essere inclusi nella matrice, dal momento che non ha nome.

+0

wow, questa è una grande punta grazie –

+0

Non esattamente insondabile: il motivo è che, se avete bisogno di più di una voce per lo stesso tipo, quindi è necessario aggiungere un nome altrimenti Unità penserà che sta effettivamente l'override la voce precedente (che è vietata). –

+3

@BrunoBrant 'insondabile' perché nessun altro contenitore DI funziona in questo modo. Vedi per es. [il mio libro] (http://amzn.to/12p90MG) per maggiori dettagli. –

3

L'utilizzo di Resolve durante il "tempo di configurazione" è accettabile e spesso utile ed è perfettamente valido per matrici o enumerabili.

Si potrebbe anche avere fatto quanto sopra registrando il tipo ILoader[] e registrazione di ciascuna delle specifiche ILoader tipi utilizzando il RegisterType overload che accetta un nome.

Quindi, ovunque sia richiesto ILoader[] (ad esempio deve essere iniettato), tutto quanto sopra verrà risolto per voi dopo il tempo di configurazione. Ovviamente, se hai bisogno di più/diversi ILoader[], tornerà a dover utilizzare Resolve durante il tempo di configurazione.

1

Se si dispone di uno scenario leggermente più complicato in cui diverse matrici di valori devono essere utilizzate in luoghi diversi, è possibile utilizzare ResolvedArrayParameter, ad es.

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");