2011-08-25 17 views
13

Estoy usando Autofac para manejar la inyección de dependencias en mi aplicación. Sin embargo, tengo un componente que hace algo de magia de reflexión en tiempo de ejecución y no sé en tiempo de compilación qué dependencias necesitará.Uso de Autofac como localizador de servicios

Por lo general, me gustaría tener este componente de referencia el contenedor directamente y resolver lo que quiera. Sin embargo, la clase que está creando una instancia de esta clase no tiene ninguna referencia al contenedor.

Efectivamente, mi componente tiene una dependencia de Autofac. Preferiría un acoplamiento más flexible, pero eso no parece ser una opción aquí. ¿Hay alguna manera de preguntar (en los argumentos del constructor, o usar la inyección de propiedad, o lo que sea) Autofac para darme una referencia al contenedor en mi constructor? ¿O hay una manera más limpia de que Autofac me proporcione un objeto localizador de servicios mágicos que pueda resolver cualquier cosa?

+2

Sin embargo, sería interesante ver qué "magia" está haciendo el componente. Tal vez hay otras formas que el patrón de localizador de servicio. ¿Podrías actualizar con algún código? –

+0

Puedo describirlo bastante bien. A medida que los mensajes llegan a través de un bus, el código determina de qué tipo el mensaje está utilizando algunos metadatos, y luego construye dicho tipo. Luego necesita encontrar todos los implementadores de 'IConsume ' (donde 'type' es el tipo de los metadatos) usando Autofac y luego llamar al método Consume en él. –

+0

Te refieres como: http://kozmic.pl/2010/03/11/advanced-castle-windsor-ndash-generic-type-factories-auto-release-and-more/ –

Respuesta

12

Sí, puedes. Basta con echar una dependencia en el IComponentContext:

public class MyComponent 
{ 
    IComponentContext _context; 
    public MyComponent(IComponentContext context) 
    { 
     _context = context; 
    } 

    public void DoStuff() 
    { 
     var service = _context.Resolve(...); 
    } 
} 

actualización de los comentarios: la IComponentContext inyecta en MyComponent depende del alcance de la cual se resolvió MyComponent. Por lo tanto, es importante considerar con qué alcance de vida MyComponent está registrado. P.ej. utilizando InstancePerLifetimeScope, el contexto siempre se resolverá en el mismo ámbito en el que vive el servicio según MyComponent.

+0

¿Funcionará esto con múltiples ámbitos de por vida? es decir, ¿el IComponentContext será el contenedor base o el alcance? –

+3

Resolverá 'IComponentContext' del ámbito en el que se resolvió' MyComponent'. Entonces, si 'MyComponent' está registrado como' InstancePerLifetimeScope', 'context' siempre se resolverá desde el alcance esperado. –

+0

Perfecto, justo lo que necesitaba. –

1

que Suponiendo que tienen dos componentes, A y B.

Si A necesita saber X sobre B antes de usarlo, esto es metadatos interrogatorio y se describe en este excellent puesto.

Además, incluso si no puede adaptar su diseño a esa publicación, debe intentar de nuevo asegurarse de que realmente necesita usar su Contenedor DI como Localizador de Servicios.

En el momento de este escrito, la mejor publicación de blog que pude encontrar describiéndolo es this uno.

+0

No estoy seguro de por qué respondería una pregunta ya bien respondida con cosas que no están relacionadas con mi pregunta ... como dije, mi problema es no saber qué "B" necesitaré resolver hasta el tiempo de ejecución. –

+1

@NikosBaxevanis +1, incluso si el OP no pareció obtenerlo. Ambas publicaciones son excelentes.Esta frase única de la publicación de Nicholas lo resume todo: "Al mismo tiempo, prácticamente ya no hay excusa para usar IContainer o IComponentContext en sus componentes". – rsenna

0

En otros casos, cuando su componente no se crea utilizando DI, aún puede utilizar el patrón de localizador de servicios. La biblioteca Common Service Locator en CodePlex es perfecta para este propósito.

Cuestiones relacionadas