Fábrica de tipo débil del castillo de Windsor

En un número muy limitado de escenarios, necesito pasar de un tipo desconocido (en el momento de la compilación) a una instancia del objeto registrado para ese tipo.

En su mayor parte, uso fábricas mecanografiadas y sé el tipo que quiero resolver en tiempo de compilación ... así que inyecto un Func<IMyType> en un constructor

... pero en este número limitado de escenarios, para evitar una llamada directa al contenedor (y así tener que hacer referencia a Windsor desde la biblioteca, que es un anti-patrón que me gustaría evitar), necesito inyectar a Func<Type,object>... que quiero contener internamente.Resolve (type) para el parámetro Type de Func.

¿Alguien tiene alguna sugerencia sobre la forma más fácil / sencilla de configurar esto?

Intenté lo siguiente, pero con esta configuración, termino omitiendo por completo TypedFactoryFacility, que definitivamente no es lo que quiero:

Kernel.Register(Component.For(typeof (Func<Type, object>)).LifeStyle.Singleton.UsingFactoryMethod(
                    (kernel, componentModel, creationContext) => 
                        kernel.Resolve(/* not sure what to put here... */)));

Gracias de antemano por cualquier ayuda.

preguntado el 08 de enero de 11 a las 23:01

2 Respuestas

Eso es fácil si recuerda que puede registrar delegados en Windsor como componentes normales:

container.Register(Component.For<Func<Type,object>>()
   .Instance(t=>container.Resolve(t)));

También puede hacerlo a través de la fábrica mecanografiada (que es el enfoque recomendado si planea resolver componentes transitorios a través de esta fábrica, ya que la fábrica mecanografiada le da un alcance) y un selector personalizado.

    container.Register(
         Component.For<YourSelector>(),
         Component.For<Func<Type,object>>().Lifestyle.Transient
             .AsFactory(x=>x.SelectedWith<YourSelector>());

Respondido el 09 de enero de 11 a las 05:01

Decidí inyectar una instancia de un IServiceProvider simple que toma un Func . ¿Alguna inquietud allí? - Jeff

¿En qué se diferencia de usar la función directamente? Cualquier preocupación se relaciona con la vida. Piense en cuándo se liberarán los objetos que extrae y si no presenta pérdidas de memoria. Eso es todo - Krzysztof Kozmic

Creo que puede usar el localizador de servicios común para esto http://commonservicelocator.codeplex.com/, que creo que Ayende escribió el apoyo de Castle Windsor para http://ayende.com/blog/archive/2008/10/02/the-common-service-locator-library.aspx. Básicamente, proporciona una forma de resolver una dependencia sin tener una dependencia en el contenedor en particular (por ejemplo, Windsor / Ninject, etc.). Termina con una dependencia del localizador de servicios común en el nivel que está resolviendo, pero al menos puede cambiar, por ejemplo, Windsor a Ninject en el nivel de la aplicación para que pueda usarse en diferentes proyectos.

Para inicializar:

ServiceLocator.SetLocatorProvider(() => { return new WindsorServiceLocator(_container); });

donde _container es su IWindsorContainer, y luego para resolver dependencias:

ServiceLocator.Current.GetInstance<MyType>();

or

ServiceLocator.Current.GetAllInstances<MyType>();

Respondido el 09 de enero de 11 a las 02:01

Realmente no quiero agregar otra dependencia de dll a mis proyectos ... y el uso del localizador de servicios generalmente se considera una mala idea ya que no demuestra expresividad en el uso de componentes (en mi humilde opinión). - Jeff

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.