2014-05-01 14 views
10

Sono nuovo in AutoFac e sto attualmente utilizzando i moduli personalizzati all'interno della configurazione della mia app per avviare alcuni sistemi F # di base. Il codice che sto usando èRisoluzione delle dipendenze AutoFac all'interno della classe del modulo

var builder = new ContainerBuilder(); 
builder.RegisterType<DefaultLogger>().As<IDefaultLogger>(); 
builder.RegisterModule(new ConfigurationSettingsReader("autofac")); 
builder.Build(); 

E all'interno della mia configurazione app ho la logica appropriata per avviare i sistemi rilevanti. Mi piacerebbe avere accesso a DefaultLogger all'interno dei miei moduli. Metadati per la classe base modulo ha le seguenti opzioni a mia disposizione:

protected virtual void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration); 

protected virtual void AttachToRegistrationSource(IComponentRegistry componentRegistry, IRegistrationSource registrationSource); 

public void Configure(IComponentRegistry componentRegistry); 

protected virtual void Load(ContainerBuilder builder); 

ho solo usato di carico finora e non riesco a vedere alcun metodo sul costruttore che mi avrebbe permesso di arrivare alla registrazione servizio.

+0

Questa è una domanda duplicata con http://stackoverflow.com/questions/23413211/autofac-cannot-resolve-dependency-in-module? –

risposta

3

La risposta si è rivelata incredibilmente semplice. Ho appena aggiunto IComponentContext come una dipendenza alla realizzazione del mio modulo

public class LocalActorSystemModule : Module { 
    private IComponentContext m_ComponentContext; // A service for resolving dependencies required by this module 

    public LocalActorSystemModule(IComponentContext componentContext) { 
     m_ComponentContext = componentContext; 
    } 

E lasciatemi autofac iniettare l'IComponentContext per me. In questo modo posso risolvere qualsiasi dipendenza richiesta all'interno del modulo.

+0

come si registra LocalActorSystemModule? –

+1

Questo non ha funzionato per me. Ho iniettato IComponentContext tramite il costruttore del modulo, ma quando ho provato ad usarlo in 'AttachToComponentRegistration' non è stato possibile risolvere ciò che volevo perché i componenti non erano ancora stati registrati. – emragins

+0

Questo può funzionare solo per un modulo se il modulo è registrato da solo e dopo aver caricato (le dipendenze richieste, ad esempio i moduli sono caricati), altrimenti non è possibile risolverlo. IMHO, l'IComponentContext dovrebbe essere iniettato in registrazioni di servizi (automaticamente), ma non per l'uso nei moduli. Penso che il comportamento non sia realmente prevedibile e non consiglierei di farlo. Pensa all'utilizzo di IComponentContext mentre il modulo non è effettivamente caricato ... quale sarebbe il risultato prima e dopo il caricamento? – Beachwalker

6

Quando si registra qualcosa dentro i moduli con autofac invece di usare il metodo RegisterType si potrebbe utilizzare il metodo Register:

builder.Register(c => 
    { 
     IComponentContext ctx = c.Resolve<IComponentContext(); 
     IDefaultLogger logger = ctx.Resolve<IDefaultLogger>(); 
     ...do something with logger... 
     return ...return object you want to register...; 
    }); 
+1

Questo non aiuta molto lo scenario che sto descrivendo. Capisco che posso risolvere le dipendenze utilizzando un IComponentContext ma ho bisogno di accedere a uno all'interno del modulo. –

+0

Qui non è possibile lasciare lo stato attivo per impostare una variabile nell'ambito esterno (il modulo nel suo esempio). In questo modo è possibile accedere solo all'interno della registrazione. Ad ogni modo, questo snipit mostra il "modo corretto" di usare il contenitore/contesto, quindi +1. Forse Jesse ha bisogno di usare gli ambiti di vita e un contenitore che ha un logger e costruisce un altro contenitore a cui viene iniettato il logger che carica i moduli forniti dal primo (hmm, sembra troppo complicato). – Beachwalker

2

Regola empirica per l'utilizzo di ogni IoC/DI Contenitore: Risolvi una volta! => quindi si ottengono tutte le dipendenze risolte per l'oggetto richiesto. Se provi a risolvere più volte, registra altri oggetti (nel frattempo) sei bloccato all'inferno. Veramente. Se si desidera recuperare oggetti per scopi diversi in luoghi e punti temporali diversi (risolti dalla registrazione centrale), è possibile che si stia cercando il Service Locator Pattern (ma spesso è descritto anche come Anti-Pattern).

I moduli hanno lo scopo di riunire le registrazioni correlate (condizionalmente) come statet nella Autofac documentation:

Un modulo è una piccola classe che può essere usata per impacchettare un insieme di componenti legate dietro una 'facciata 'per semplificare la configurazione e la distribuzione .

... quindi se sono solo una somma di registrazioni e il contenitore non è stato ancora creato non è possibile risolvere e utilizzare immediatamente un componente (anche precedentemente registrato) (tranne chiamare un metodo sul registrante stesso tramite gli hook OnActivate * o quando si utilizza la registrazione dell'istanza, ma penso che questo non sia il caso del tuo esempio). I componenti sono solo nello stato di registrazione ma il contesto completo non è pronto per la risoluzione. Cosa succederebbe se si annullasse la registrazione in un altro modulo? Allora avresti iniettato diversi oggetti ... cattiva idea. Forse dovresti riconsiderare il design della tua applicazione e quali oggetti hanno quali responsabilità.

A proposito: La registrazione è un problema trasversale che spesso viene "iniettato/risolto" chiamando una fabbrica statica separata o un servizio invece di fare costruttore iniezione/proprietà (vedi utilizzo di Common.Logging per esempio).

public class MyModule : Module 
{ 
    private static readonly ILog Log = LogManager.GetLogger<MyModule>(); 

    protected override void Load(ContainerBuilder builder) 
    { 
     Log.Debug(msg => msg("Hello")); // log whatever you want here 
    } 
} 

Si può anche provare ad usare AOP librerie e tessere la dipendenza nel modulo (utilizzando la riflessione).Ma non penso che valga la pena provare solo per l'accesso a un modulo.

In ogni caso: @ mr100 ha già mostrato l'utilizzo corretto durante la registrazione. Qui è anche possibile gestire l'attivazione ecc. Ma non effettuare la registrazione per il modulo stesso.

Problemi correlati