2010-09-15 15 views
9

Estoy tratando de inyectar una dependencia a mis controladores de MVC como estoUnidad Marco de la COI con el constructor por defecto

private static void RegisterContainer(IUnityContainer container) 
{    
    container 
     .RegisterType<IUserService, UserService>() 
     .RegisterType<IFacebookService, FacebookService>(); 
} 

La clase tiene un constructor UserService así ...

public UserService(): this(new UserRepository(), new FacebookService()) 
{ 
    //this a parameterless constructor... why doesnt it get picked up by unity? 
} 

public UserService(IUserRepository repository, IFacebookService facebook_service) 
{ 
    Repository=repository; 
    this.FacebookService=facebook_service; 
} 

La excepción me estoy haciendo es el siguiente ...

el tipo de corriente, Repositories.IUserRepository, es una interfaz y no puede ser construido. ¿Te falta un mapeo tipo ?

Parece que está intentando inyectar un constructor en el servicio, pero el valor predeterminado sería suficiente? ¿Por qué no está mapeando al constructor sin parámetros?

+0

¿Cuáles son '' Repository' y this.FacebookService'? – SwDevMan81

Respuesta

25

La convención por defecto Unidad (que es bastante claramente en la documentación) es elegir el constructor con la mayor cantidad de parámetros. No se puede simplemente hacer una afirmación general de que "no es verdad que IoC encuentre el constructor más específico, si no se especifican los parámetros del constructor mientras se registra un tipo, automáticamente llamará al constructor predeterminado". Cada implementación de contenedor puede tener y tiene diferentes valores predeterminados.

En el caso de Unity, como dije, elegirá el constructor con más parámetros. Si hay dos que tienen la mayoría de los parámetros, entonces será ambiguo y arrojará. Si desea algo diferente, debe configurar el contenedor para hacer eso.

Las opciones son:

Poner el atributo [InjectionConstructor] en el constructor desea denominado (no se recomienda, pero rápido y fácil).

Uso de la API:

container.RegisterType<UserService>(new InjectionConstructor()); 

Uso de configuración XML:

<container> 
    <register type="UserService"> 
    <constructor /> 
    </register> 
</container> 
+0

¡Qué lástima que incluso el anticuado Castillo de Windsor elija el constructor mejor igualado y la Unidad aún no pueda! –

+0

Fue una compensación deliberada. Unity puede resolver tipos concretos que no están registrados en el contenedor, Windsor no puede que yo sepa. Esto hace que "mejor emparejado" sea realmente ambiguo, por lo que optamos por un valor predeterminado más determinista. –

+1

Gracias por aclararnos. Veo que mi comentario contiene argumentos fuertes innecesarios. Eso debería ser "La unidad no selecciona automáticamente el constructor" en lugar de "no puedo" :) Parece que eligieron otra ruta por decisión de diseño también http://stackoverflow.com/a/499675/929902 De todos modos, estoy contento con Unity y con es flexibilidad. –

0

No puedo hablar con Unity específicamente, pero los contenedores IoC generalmente intentarán usar el constructor más específico que puedan encontrar porque es un constructor.

Si hay un constructor que toma dos dependencias para inyección, entonces presumiblemente son necesarias para usar el objeto; el constructor predeterminado tendrá que hacer algo para cumplirlos si el contenedor lo llama. El trabajo del contenedor es cumplir con las dependencias, entonces, ¿por qué dejaría en manos de la clase hacer eso si no se le ordena dejarlo en la clase?

A su pregunta específica, de acuerdo con su código:

private static void RegisterContainer(IUnityContainer container) 
{    
    container 
     .RegisterType<IUserService, UserService>() 
     .RegisterType<IFacebookService, FacebookService>(); 
} 

IUserRepository no está registrado. Añada una línea como

.RegisterType<IUserRepository, UserRepository>() 
+0

no es cierto que IoC encuentre el constructor más específico, si no especifica los parámetros del constructor al registrar un tipo, automáticamente llamará al constructor predeterminado. – TalentTuner

+0

No sé qué contenedores ha usado, pero casi nunca especifico constructores en mis asignaciones. Sé con certeza que StructureMap preferirá un constructor más satisfactorio para el constructor predeterminado: lo estoy usando en mi proyecto actual, y así es como pruebo unitariamente algunos de los objetos que tienen que tener un constructor predeterminado (WCF Services, por ejemplo).) Estoy bastante seguro de que Castle Windsor también preferirá un constructor más específico. – arootbeer

+1

@saurabh En mi experiencia con Unity, cuando no se especifican parámetros, se utiliza el constructor más específico. –

Cuestiones relacionadas