2009-03-13 11 views
13

Sono ancora abbastanza nuovo per l'utilizzo di Autofac e una cosa che mi manca nella documentazione ed esempi è come rendere più semplice arrivare al contenitore configurato da diversi punti in un'applicazione web.Autofac nelle applicazioni Web, dove dovrei conservare il contenitore per un facile accesso?

So che posso utilizzare la fabbrica di controller Autofac per risolvere automaticamente le dipendenze iniettate dal costruttore per i controller, ma per quanto riguarda le altre cose che potrebbe essere necessario risolvere non ancora iniettate.

C'è uno schema ovvio di cui non sono a conoscenza per questo?

Grazie!

+4

BTW questa domanda è stata posta quando MVC era alla versione 2. In MVC 3, 'DependencyResolver.Current' è tutto ciò che serve se si utilizza Autofac o altro. –

risposta

11

Prima di tutto, provare a non utilizzare eccessivamente il contenitore IoC. È ottimo per "collegare" controller, viste e servizi, ma gli oggetti che devono essere creati durante il runtime dovrebbero essere creati dagli oggetti factory e non dal container. Altrimenti ottieni Container.Resolve chiama tutto attraverso il tuo codice, legandolo al tuo contenitore. Queste dipendenze extra vanificano lo scopo dell'uso di IoC. Nella maggior parte dei casi posso ottenere risolvendo solo una o due dipendenze al livello più alto della mia applicazione. Il contenitore IoC risolverà quindi ricorsivamente la maggior parte delle dipendenze.

Quando ho bisogno del contenitore altrove nel mio programma, ecco un trucco che uso spesso.

public class Container : IContainer 
{ 
    readonly IWindsorContainer container; 

    public Container() 
    { 
     // Initialize container 
     container = new WindsorContainer(new XmlInterpreter(new FileResource("castle.xml"))); 

     // Register yourself 
     container.Kernel.AddComponentInstance<IContainer>(this); 
    } 

    public T Resolve<T>() 
    { 
     return container.Resolve<T>(); 
    } 
} 

Ho disposto il contenitore in una classe Contenitore come questa. Si aggiunge al contenitore incartato nel costruttore. Ora le classi che hanno bisogno del contenitore possono avere un iniettore IContainer. (l'esempio è per Castle Windsor ma probabilmente può essere adattato per AutoFac)

1

Il modo usuale per farlo è quello di memorizzare il contenitore in una variabile statica nella classe dell'app globale.

+2

Ah, ma fai attenzione a quale contenitore immagazzini! Non ti interessa il contenitore delle applicazioni, questo è sicuro! – n8wrl

30

Il "modo" Autofac deve avere un parametro costruttore IContext. Autofac inietterà un oggetto che può essere utilizzato per risolvere i tipi.

Il contesto è di solito il contenitore dietro le quinte, IContainer implementa l'interfaccia IContext, anche se IContext è limitata a risolve solo facendo.

So che il contenitore non deve essere "sovrautilizzato", ma ho, come l'OP, classi che richiedono la risoluzione di tipi che non sono noti in anticipo (e quindi non possono essere usati come parametri del costruttore). Trovo utile in questi casi, pensare al contenitore come a un altro servizio che può essere utilizzato per risolvere altri servizi e iniettarlo come qualsiasi altro servizio.

Se ritieni che l'uso di IContext ti leghi ad Autofac e che sia necessario estrapolarlo con la tua interfaccia, è solo questione di registrare una classe wrapper IContext con il tuo contenitore.

Aggiornamento: in Autofac 2, il IContext si chiama IComponentContext.

+0

Perché non inserire una fabbrica invece? – TrueWill

+0

@TrueWill - ... e la differenza è? –

+0

Ancora una volta, l'indizio qui è che non sempre (e specialmente con il codice legacy non costruito con DI in mente) sono i tipi di servizi richiesti non noti al momento della compilazione. Quindi è richiesta una fabbrica tipizzata "non fortemente". L'IContext è proprio questo, una fabbrica in grado di produrre istanze dei tipi che si cerca di risolvere. –

6

La risposta di Peter Lillevold è corretta: è possibile accedere al contenitore da qualsiasi componente assumendo una dipendenza dall'interfaccia IContext.

Se si in realtà è necessario il riferimento effettivo del contenitore, vedere Autofac.Integration.Web.IContainerProviderAccessor.

8

La disponibilità di contenitori IOC a livello globale non è ottimale. Anche passing container is not encouraged.

Se non è possibile utilizzare l'iniezione di dipendenza (è necessario creare \ oggetti richiesta dopo componente è stato creato), allora è possibile:

  1. Utilizzare fabbriche codificati a mano (in fabbrica viene iniettato agli usi dei componenti e dei componenti fabbrica per creare altri oggetti)
  2. Utilizzare Autofac delegate factories o new auto-generated factories in Autofac 2.
+0

huzzah per non utilizzare il contenitore come localizzatore di servizi – JJS

Problemi correlati