2016-04-24 36 views
5

mi chiedevo è che non c'è alcun effetto collaterale per la registrazione del contenitore in séRegistrati contenitore stesso Utilizzando Autofac

IContainer container; 
ContainerBuilder builder = new ContainerBuilder(); 
container = builder.Build(); 
builder.RegisterInstance(container).As<IContainer>(); 

e usarlo come questo

builder.RegisterType<IManagmentServiceImp>().As<ManagmentServiceImp>() 
    .WithParameter(new ResolvedParameter(
      (pi, ctx) => pi.ParameterType == typeof(IContainer) && pi.Name == "Container", 
      (pi, ctx) => container 
)); 

o se sarà anche il lavoro.

risposta

10

Il codice non è sicuro perché si registra un'istanza prima che sia stata inizializzata.

Se è necessario accedere al contenitore all'interno di un componente (che non è una buona idea) è possibile avere una dipendenza da ILifetimeScope che hanno metodi Resolve.

public class ManagmentServiceImp 
{ 
    public ManagmentServiceImp(ILifetimeScope scope) 
    { 
    } 
} 

ILifetimeScope viene registrato automaticamente entro Autofac non è necessario aggiungere registrazione per esso.

Vedere Controlling Scope and Lifetime da documentazione Autofac per ulteriori informazioni.

A proposito, non è una buona pratica avere dipendenza dal proprio contenitore IoC. Sembra che tu usi l'anti-pattern Service Locator. Se è necessario il contenitore per pigri la dipendenza del carico, è possibile utilizzare la composizione con Func<T> o Lazy<T>

public class ManagmentServiceImp 
{ 
    public ManagmentServiceImp(Lazy<MyService> myService) 
    { 
     this._myService = myService; 
    } 

    private readonly Lazy<MyService> _myService; 
} 

In questo caso, verrà creata la prima volta che l'accesso è MyService.

Vedere Implicit Relationship dalla documentazione Autofac per ulteriori informazioni.

1

Poiché è necessario fornire un'istanza del contenitore a builder.RegisterInstance(), è necessario inizializzarlo PRIMA di passarlo come argomento, che non si sta attualmente facendo. Tuttavia, se si struttura il builder del contenitore per creare la registrazione AFTER (e l'inizializzazione del contenitore), è possibile risolvere correttamente l'istanza del contenitore nella classe.

Si prega di notare che questo è certamente un odore di design in Dipendenza Iniezione e non si dovrebbe assolutamente farlo. Il tuo contenitore/kernel dovrebbe esistere solo al livello più alto del tuo grafo di oggetti. Se inizi a iniettare il tuo contenitore, sei quasi certamente sulla strada per un Anti-Pattern Locator del servizio.

void Main() 
{ 
    IContainer container = new ContainerBuilder().Build(); 
    ContainerBuilder builder = new ContainerBuilder(); 

    builder.RegisterInstance(container).As<IContainer>(); 

    builder.RegisterType<ManagementServiceImp>().As<IManagmentServiceImp>() 
     .WithParameter(new ResolvedParameter(
      (pi, ctx) => pi.ParameterType == typeof(IContainer) && pi.Name == "Container", 
      (pi, ctx) => container 
    )); 

    container = builder.Build(); 
    var instance = container.Resolve<IManagmentServiceImp>(); 
} 

public class ManagementServiceImp : IManagmentServiceImp 
{ 
    private IContainer _container; 

    public ManagementServiceImp(IContainer Container) 
    { 
     _container = Container; 
     _container.Dump(); 
    } 
} 

public interface IManagmentServiceImp { } 
+0

@torvin in che modo è il contenitore non-configurato e in che modo questo non risolve il bisogno del PO? –

+0

scusate ho rimosso per errore il mio commento.Era "Questo è sbagliato, registrerà un contenitore non configurato" – torvin

+0

@torvin non hai ancora spiegato come questo non soddisfi le esigenze dell'OP. –

0

Mentre non rispondo alla domanda. Cercare di ottenere un handle del contenitore in una classe di servizio o qualcosa di diverso da un equivalente di IModule è un odore di codice.

Il codice di servizio non deve essere informato su IOC IMO.

+3

Sebbene io abbia assolutamente la stessa sensazione di usare il contenitore in qualcosa di diverso dalla registrazione, ci sono situazioni in cui posso pensare a quale richiesta di un piccola bruttezza. Personalmente, penso che non dovresti dare questo tipo di feedback senza offrire un'alternativa per l'interrogante ... – DotBert

1

È possibile utilizzare questo metodo di estensione:

public static void RegisterSelf(this ContainerBuilder builder) 
{ 
    IContainer container = null; 
    builder.Register(c => container).AsSelf(); 
    builder.RegisterBuildCallback(c => container = c); 
} 

usare in questo modo: builder.RegisterSelf();