2009-07-31 13 views
5

No se puede conseguir mi cabeza alrededor del paso de parámetros en Autofac, el código siguiente no funciona:Autofac paso de parámetros y autowiring

class Config { 
    public Config(IDictionary<string, string> conf) {} 
} 

class Consumer { 
    public Consumer(Config config) {} 
} 

void Main() 
{ 
    var builder = new Autofac.Builder.ContainerBuilder(); 
    builder.Register<Config>(); 
    builder.Register<Consumer>(); 
    using(var container = builder.Build()){ 
     IDictionary<string,string> parameters = new Dictionary<string,string>(); 
     var consumer = container.Resolve<Consumer>(Autofac.TypedParameter.From(parameters)); 
    } 
} 

que arroja:

DependencyResolutionException: The component 'UserQuery+Config' has no resolvable constructors. Unsuitable constructors included: 
Void .ctor(System.Collections.Generic.IDictionary`2[System.String,System.String]): parameter 'conf' of type 'System.Collections.Generic.IDictionary`2[System.String,System.String]' is not resolvable. 

pero el siguiente código hace trabajo:

IDictionary<string,string> parameters = new Dictionary<string,string>(); 
var config = container.Resolve<Config>(Autofac.TypedParameter.From(parameters)); 
var consumer = container.Resolve<Consumer>(Autofac.TypedParameter.From(config)); 
+2

Su pregunta no es muy clara. Por el bien de aquellos de nosotros que no somos usuarios de autofac, ¿podría mostrar las declaraciones de p, config, TypedParameter.From y container.Resolve? Además, especifique de qué forma "no funciona": ¿error de tiempo de compilación? ¿Excepción? –

+0

clarificado con un ejemplo ejecutable en ej. LINQPad (referencia Autofac.dll) –

Respuesta

18

repetir aquí la respuesta de la lista de correo Autofac:

Los parámetros pasados ​​a resolver solamente relacionado con el ejecutor directo del el servicio que está resolviendo, por lo que el paso de parámetros de configuración para la determinación convocatoria de won Consumidor no funciona La forma de evitar esto es cambiar su inscripción al Consumidor a:

builder.Register((c, p) => new Consumer(c.Resolve<Config>(p))); 
+0

supongo que quiere decir: builder.Register ((c, p) => nuevo Consumidor (c.Resolver (p))); porque eso funciona ¡perfecto! Gracias Nicholas! –

+3

+1 finalmente alguien que conoce autofac :-) – galaktor

+4

Por "finalmente alguien que conoce autofac" se refiere al autor, sí, claro :) – uriDium

0

Autofac es, obviamente, tratando de resol ve el parámetro de tu clase Config en la suposición de que el Diccionario en sí es un tipo resoluble. No sé la sintaxis de autofac sobre cómo hacerlo. Pero probablemente necesite hacer más pasos cuando registre el tipo de Config, e. gramo. dándole un delegado que pasa en un nuevo diccionario.

+0

¡tienes razón! pero luego surge el siguiente problema, si registro Config como sigue: constructor. Registre ((c, p) => nueva Config (p.TypedAs >())); p ¡está vacío en el momento de la resolución! –

+0

Hm. Tal vez sea porque le das a autofac un delegado, pero luego el delegado aún no tiene el diccionario en tiempo de ejecución. Intente proporcionar un nuevo diccionario en su delegado, algo como esto (tenga en cuenta que aún no conozco las formulaciones exactas para autofac): builder.Register ((c) => new Config (new Dictionary ())); – galaktor

+0

no siempre le dará a Config un diccionario vacío? a pesar de los argumentos que se pasan en el momento de la resolución? –

0

Por desgracia, los contenedores IoC como Autofac no viene equipado con un "por favor leer mi mente módulo".

Lo que estás tratando de hacer es básicamente decir "Sé que uno de los tipos implicados aquí necesita un diccionario, y necesito un servicio de tipo Consumer, ¿puedes tratar de averiguar qué es lo que soy? tomando sobre y simplemente hacer el lo correcto? ".

Si resuelve un servicio y especifica un parámetro, se intentará utilizar ese parámetro para ese servicio en particular. El contenedor no intentará propagar ese valor de parámetro a ninguna dependencia.

+0

seguro, mi primer intento fue ingenuo, pero no fuera, si los parámetros se habían tratado como registros que tenía trabajo? –

+0

Podría ser, AutoFac debería ser capaz de resolverlo, pero necesitaría prerregistrar los parámetros como servicios con AutoFac. Personalmente, no recomiendo servicios con parámetros de constructor, es invariablemente un servicio con fugas, ya que filtra los detalles de implementación en el código que lo usa, hace que sea más difícil reemplazar el servicio más adelante. Considere como ejemplo un servicio donde le pasará un nombre de archivo de configuración, ¿qué más si luego decide usar un servicio que lee la configuración desde una base de datos? –

+0

sí, sé que mi solución no es inmediata, pero lo que pasa es que quiero que el usuario pueda configurar el tipo de servicio que se utilizará. Pero ese servicio también necesita configuraciones diferentes, así que ahora estas configuraciones de servicios se pasan como IDictionary ... me encantaría mejores soluciones, pero esta cosa de la fábrica es mi mejor intento hasta ahora .. –

Cuestiones relacionadas