2009-03-13 11 views
13

Todavía soy bastante nuevo en el uso de Autofac y una cosa que echo de menos en la documentación y ejemplos es cómo hacer que sea más fácil llegar al contenedor configurado desde diferentes lugares en una aplicación web.Autofac en aplicaciones web, ¿dónde debería guardar el contenedor para facilitar el acceso?

Sé que puedo usar el controlador Autofac de fábrica para resolver automáticamente las dependencias de constructores inyectados para los controladores, pero qué hay de las otras cosas que podría necesitar resolver y que aún no se han inyectado.

¿Existe un patrón obvio del que no estoy enterado?

Gracias!

+4

BTW esta pregunta se hizo cuando MVC estaba en la versión 2. En MVC 3, 'DependencyResolver.Current' es todo lo que necesita ya sea que esté utilizando Autofac u otra cosa. –

Respuesta

11

En primer lugar intente no abusar del contenedor de IoC. Es ideal para "conectar" controladores, vistas y servicios, pero los objetos que deben crearse durante el tiempo de ejecución deben ser creados por objetos de fábrica y no por el contenedor. De lo contrario, obtienes Container.Resolve llamadas a través de tu código, atándolo a tu contenedor. Estas dependencias adicionales frustran el propósito de usar IoC. En la mayoría de los casos, solo puedo resolver una o dos dependencias en el nivel superior de mi aplicación. El contenedor IoC resolverá recursivamente la mayoría de las dependencias.

Cuando necesito el contenedor en otro lugar de mi programa, aquí hay un truco que suelo usar.

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>(); 
    } 
} 

Envuelvo el contenedor en una clase de contenedor como esta. Se agrega al contenedor envuelto en el constructor. Ahora las clases que necesitan el contenedor pueden tener un IContainer inyectado. (el ejemplo es para Castle Windsor pero probablemente se puede adaptar para AutoFac)

1

La forma habitual de hacerlo es almacenar el contenedor en una variable estática en su clase de aplicación Global.

+2

¡Ah, pero tenga cuidado con el contenedor que almacena! ¡No es seguro que uses el contenedor de la aplicación! – n8wrl

30

El "camino" de Autofac es tener un parámetro de constructor IContext. Autofac inyectará un objeto que se puede usar para resolver tipos.

El contexto es por lo general el contenedor detrás de las escenas, IContainer implementa la interfaz IContext, aunque IContext se limita a sólo resuelve haciendo.

Sé que el contenedor no debe ser "usado en exceso", pero tengo, como el OP, clases que requieren resolver tipos que no se conocen de antemano (y por lo tanto no pueden usarse como parámetros de constructor). Me parece útil en estos casos, pensar en el contenedor como otro servicio que se puede usar para resolver otros servicios e inyectarlo como cualquier otro servicio.

Si siente que el uso de IContext lo vincula a Autofac y necesita abstraerlo con su propia interfaz, es solo cuestión de registrar una clase de contenedor IContext con su contenedor.

Actualización: en Autofac 2, el IContext se llama IComponentContext.

+0

¿Por qué no inyectar una fábrica en su lugar? – TrueWill

+0

@TrueWill - ... y la diferencia es? –

+0

Una vez más, la clave aquí es que no siempre (y especialmente con el código heredado no construido con DI en mente) son los tipos de servicios requeridos que no se conocen en tiempo de compilación. Por lo tanto, se requiere una fábrica de tipos "no fuertemente". IContext es solo eso, una fábrica que puede producir instancias de los tipos que uno intenta resolver. –

6

La respuesta de Peter Lillevold anterior es correcta: puede acceder al contenedor desde cualquier componente tomando una dependencia de la interfaz IContext.

Si realmente necesita la referencia del contenedor real, vea Autofac.Integration.Web.IContainerProviderAccessor.

8

Tener un contenedor de COI disponible en todo el mundo no es una buena práctica. Incluso passing container is not encouraged.

Si no se puede utilizar la inyección de dependencias (que necesita para crear objetos \ petición después de componente ha sido creado), entonces usted puede:

  1. Use fábricas de codificación manual (fábrica se inyecta a los usos de los componentes y componentes fábrica para crear otros objetos)
  2. Utilice Autofac delegate factories o new auto-generated factories in Autofac 2.
+0

huzzah por no usar el contenedor como localizador de servicios – JJS

Cuestiones relacionadas