2009-01-15 6 views
17

Tome el siguiente programa inútil:La resolución de clases sin registrarse utilizando el castillo de Windsor

class Program 
{ 
    static void Main(string[] args) 
    { 
     IUnityContainer unityContainer = new UnityContainer(); 
     IWindsorContainer windsorContainer = new WindsorContainer(); 

     Program unityProgram = unityContainer.Resolve<Program>(); 
     Program castleProgram = windsorContainer.Resolve<Program>(); 
    } 
} 

El UnityContainer me va a devolver una instancia del programa, en tanto que el contenedor Windsor arrojará un ComponentNotFoundException.

Puedo ver argumentos para ambos comportamientos y no me importa con qué termine, sin embargo, Prism V2 Drop 8 (el último al momento de escribir) se basa en el comportamiento de Unity internamente, solicitando clases que no se han registrado .

En lugar de buscar y registrar todas estas clases para Prism, prefiero que Windsor se comporte como Unity. No he encontrado nada en google que me ayude a hacer esto (aunque mi terminología puede ser incorrecta) y la documentación de Windsor es bastante mala ...

¿Alguien puede sugerir una solución a este problema?

+1

¿no este tipo de derrota el propósito de una COI? Si hubiera resuelto IProgram, ¿encontraría una definición de clase que implemente IProgram en ese caso? – jishi

+0

Supongo que todavía tiene la ventaja de la inyección de dependencia en la clase, incluso si no utiliza una interfaz. –

+3

jishi: las respuestas a sus preguntas son no y no. No, no infringe el propósito de IoC. No, no mapea las interfaces sin que estén registradas. – Anthony

Respuesta

9

Windsor actualmente no es compatible con eso, y es por diseño. El razonamiento es que debe registrar explícitamente los tipos que necesita para no tener un objeto mal configurado.

Sin embargo, existe la posibilidad de que se agregue un gancho para crear un tipo no registrado en algún momento en el futuro cercano, ya que esto es necesario para la instalación de integración WCF. (Edición - que se añadió en v2.1 - echar un vistazo a ILazyComponentLoader s)

De todos modos, independientemente de cargadores de componentes perezosos, lo mejor que puede hacer es usar API fluida a lote registrar todos los tipos partir de un ensamblaje haciendo coincidir sus criterios necesarios por adelantado. No es mucho más código y dormirás mejor por las noches.

Use cargadores perezosos sólo si tiene realmente no hay suficiente información en el arranque (en su composición raíz) para determinar qué componentes que necesita.

+0

¿Por qué Windsor WCF Integration Facility debe crear tipos no registrados? – urig

+3

@urig - para que pueda decir obtener tipos que están especificados en su web.config solamente, y no duplicar el registro en el contenedor. DRY. –

6

Windsor no admite que fuera de la caja, pero se pueden crear métodos de extensión para hacer esto:

static class WindsorExtensions 
{ 
    public static object ResolveType(this IWindsorContainer container, Type type) 
    { 
     if (type.IsClass && !container.Kernel.HasComponent(type)) 
      container.Kernel.AddComponent(type.FullName, type, LifestyleType.Transient); 
     return container.Resolve(type); 
    } 

    public static T ResolveType<T>(this IWindsorContainer container) 
    { return (T)ResolveType(container, typeof(T)); } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     IUnityContainer unityContainer = new UnityContainer(); 
     IWindsorContainer windsorContainer = new WindsorContainer(); 

     Program unityProgram = unityContainer.Resolve<Program>(); 
     Program castleProgram = windsorContainer.ResolveType<Program>(); 
    } 
} 
+0

Esto no duplica por completo la funcionalidad si Unity: solo la clase de nivel superior se registrará automáticamente. ¿Qué pasa si la clase A depende de la clase concreta B, ni A ni B están registrados, e intenta resolver A? Unity se encargará de esto, pero su código anterior no lo hará. – Anthony

+0

Eso es verdad.Sin embargo, en todos los casos en que necesitaba resolver un tipo no registrado, nunca necesité la resolución "recursiva" de otras dependencias no registradas que usted describe. Debería ser posible implementar esto encima de Windsor, también, pero personalmente, no lo necesitaba. –

2

Krzysztof que no tenga miedo de enlace a su propio blog aquí :) http://devlicious.com/blogs/krzysztof_kozmic/archive/2009/11/16/castle-windsor-lazy-loading.aspx

Además, he encontrado esta sencilla aplicación útil en mi aplicación WPF, retire el contraint cuerda y que se encuentran cerca del caso general

public class ViewModelLoader : Castle.MicroKernel.Resolvers.ILazyComponentLoader { 
    public IRegistration Load(string key, Type service) 
    { 
     if (service == null) 
      return null; 
     if (service.Name.EndsWith("ViewModel", StringComparison.CurrentCultureIgnoreCase)) 
      return Component.For(service).Named(key); 
     else 
      return null; 
    } 
} 
Cuestiones relacionadas