7

Ahora tengo algunos servicios que se definen en un ensamblaje que no depende de un contenedor IoC (Ninject en mi caso). En el proyecto principal, tengo un IRepository para el acceso a datos registrado en el contenedor.Práctica general de la IoC: ¿es incorrecto que los servicios dependan el uno del otro?

this.Bind<IRepository>().To<EntityFrameworkRepository<MyDatabaseEntities>>(); 

También he IAuthenticationService servicios y IErrorLogger registrada, cuya aplicación concreta Quiero usar el repositorio de su lógica. Sin embargo, no estoy seguro de cómo lograr esto mejor. Actualmente, mi constructor en ambas implementaciones concretas tomar un parámetro IRepository y lo paso en cuando les Registro:

this.Bind<IAuthenticationService>().To<MyAuthenticationService>(). 
       WithConstructorArgument("myRepository", ctx => ctx.Kernel.Get<IRepository()); 

Aquí acabo de decirle al contenedor para agarrar la instancia IRepository y pasarlo al constructor.

No me pareció correcto hacer que mi conjunto de servicios dependa de ninject o incluso del localizador de servicios comunes (CSL), pero tampoco estoy seguro de mi forma actual. Estoy buscando opiniones y soluciones alternativas.

Si mis otros servicios no usan un IRepository, tendría que crear nuevas implementaciones concretas de estos servicios para cada tipo de tipo de IRepository subyacente (por ejemplo, un AuthenticationService para datos falsos y reales). Sería mucha repetición lógica.

Respuesta

6

Su conjunto de servicio no debe depender de Ninject, solo en las interfaces para las que registre sus tipos concretos. El contenedor IoC debe ser solo la raíz agregada para inyectar dependencias en tus clases. El conjunto que contiene la raíz agregada/el núcleo Ninject por otro lado dependerá de todos los ensamblajes que contengan los tipos concretos (¿de qué otro modo podría resolverlos?).

En general con la COI debe aplicar la Hollywood principle aquí - usted debe dar las dependencias a las instancias de objetos concretos (mediante la inyección de constructor si es posible), no vamos a las instancias de objetos preguntan por sus dependencias.

El ejemplo que utiliza para WithConstructorArgument(), no se necesita en absoluto en realidad, ya que la resolución de dependencias funciona de forma recursiva: se ha registrado tanto IRepository y IAuthenticationService con el contenedor, por lo que sabe cómo resolver ambos. Como IAuthenticationService está vinculado a AuthenticationService, no necesita especificar el argumento constructor ya que es del tipo IRepository y se resolverá automáticamente.

En cuanto a la repetición - por supuesto, tendrá que crear implementaciones diferentes para IRepository para distintos tipos de depósito si quiere enviar un comportamiento diferente de estos repositorios.

+0

¡Excelente información! Tiene razón, no necesitaba especificar el WithConstructorArgument en absoluto. Fueron inyectados automáticamente. Otra pregunta es ¿qué ocurre si registro 2 implementaciones de IRepository, cada una con un nombre diferente? Entonces quiero especificar el que inyectar. Sé que hay un NamedAttribute con Ninject, pero para evitar agregar una dependencia de Ninject a mi ensamblado de servicio no me gustaría usar eso. Entonces, especificar manualmente sería el camino a seguir en este caso? FYI, mi preocupación por la repetición no era sobre IRepository sino sobre las otras clases de servicio. – Adam

+2

Para Ninject podría usar 'WhenInjectedInto ()' donde Foo es su clase de servicio.Normalmente, solo registraría una implementación concreta de su repositorio; las de datos falsos y las pruebas no se deberían registrar como parte de su aplicación principal, solo en un contenedor de prueba por separado – BrokenGlass

+0

Perfecto, gracias de nuevo. – Adam

Cuestiones relacionadas