patron manejo inyeccion framework dependencias control c# dependency-injection unity-container ioc-container

c# - manejo - ¿Cómo usar la interfaz de repositorio que usa genéricos con inyección de dependencia?



manejo de dependencias c# (5)

¿Esta bien?

Por supuesto. Existe una preferencia personal sobre si se debe usar inyección de constructor como la que tiene o inyección de propiedad. La inyección de constructores es más limpia, ya que no tiene que tener muchos parámetros para su constructor, pero también es más seguro.

¿Cuál es el punto de la Unidad para registrar la interfaz al tipo concreto?

Una razón es para que pueda probar la unidad MyClass sin tener que usar su repositorio real que llegue a una base de datos. Puede "falsificar" el repositorio para devolver los valores codificados para probarlos.

Estoy intentando usar la siguiente Interfaz de repositorio genérico para DI e inyección de constructor:

public interface IRepository<TEntity> : IDisposable where TEntity : class

El problema es que para definir una instancia de la Interfaz, debo proporcionar el tipo de clase así:

private IRepository<Person> _personRepository;

El problema con esto es si estoy usando DI (y estoy usando Unity para el framework IoC), entonces tengo que definir múltiples instancias en mi constructor para obtener todas las interfaces de repositorio con las que necesito trabajar de esta manera:

public MyClass(IRepository<Person> personRepository, IRepository<Orders> ordersRepository, IRepository<Items> itemsRepository, IRepository<Locations> locationsRepository) { _personRepository = personRepository; _OrdersRepository = ordersRepository; _itemsRepository = itemsRepository; _locationsRepository = locationsRepository; }

Preguntas:

  1. ¿Esta bien?
  2. Si no, ¿dónde estoy perdido en este concepto?
  3. Incluso si esto es correcto, ¿qué sentido tiene Unity registrar la interfaz en concreto? Ya lo hice porque el repositorio genérico me obligó a declarar.

¡Por favor ayúdenme a aclarar esto, y agradezco toda su ayuda!


Como señaló D Stanley, una dependencia debe ser una interfaz concreta. De lo contrario, ¿dónde vas a declarar T? Su clase dependiente podría ser genérica, pero todavía tiene que decir "T es una persona" en algún momento.

Dicho esto, Unity maneja el registro de tipos genéricos bastante bien.

Digamos que implementa IRepository<T> con un Repository<T> clase genérico Repository<T> que envuelve un DbSet<T> (o lo que sea).

El siguiente registro y resuelve funcionará (lo que incluye la inyección en cualquier constructor):

container.RegisterType(typeof(IRepository<>), typeof(Repository<>)); // no specific registration needed for the specific type resolves container.Resolve(<IRepository<Person>); container.Resolve(<IRepository<Order>);

Si necesita una anulación específica de un tipo (dice que el repositorio de Elementos es especial por alguna razón, por lo que tiene una clase ItemRepository totalmente implementada), simplemente registre esa implementación específica después de la genérica:

container.RegisterType<IRepository<Item>, ItemRepository>();

La resolución de IRespository<Item> ahora obtendrá su implementación específica.

Para el registro, creo que esto solo se puede hacer en código y no en archivos de configuración. Alguien puede corregir esa suposición.


Esto parece correcto, excepto un punto faltante; necesita el patrón UnitOfWork para habilitar las transacciones. Sin el patrón UnitOfWork aplicado, todos los repositorios intentan confirmar operaciones de DB en diferentes contextos.


Necesitaba hacer esto usando el archivo de configuración. En realidad es bastante fácil, pero me tomó un tiempo darme cuenta.

En este ejemplo, tenemos una interfaz IRepository<T> y tiene 2 implementaciones:

  1. OneRepository
  2. TwoRepository

Luego tenemos una clase llamada Worker que depende de IRepository<One> e IRepository<Two> . Pedimos a unity que cree una instancia de Worker para nosotros y descubra las dependencias del archivo de configuración.

Interfaz e Implementación

Todos estos están en el espacio de nombres ConsoleApplication1 en este ejemplo.

public class Worker { private readonly IRepository<One> one; private readonly IRepository<Two> two; public Worker(IRepository<One> one, IRepository<Two> two) { this.one = one; this.two = two; } public string DoOne() { return this.one.Add(new One()); } public string DoTwo() { return this.two.Add(new Two()); } } public interface IRepository<T> { string Add(T t); } public class OneRepository : IRepository<One> { public string Add(One t) { return "One"; } } public class TwoRepository : IRepository<Two> { public string Add(Two t) { return "Two"; } } public class One { } public class Two { }

Configuración de la unidad

Tenga en cuenta que instruimos a la unidad y le dimos el nombre del conjunto. Luego registramos las 2 implementaciones.

<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" /> </configSections> <unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> <assembly name="ConsoleApplication1" /> <container> <register type="ConsoleApplication1.IRepository[[ConsoleApplication1.One]]" mapTo="ConsoleApplication1.OneRepository" /> <register type="ConsoleApplication1.IRepository[[ConsoleApplication1.Two]]" mapTo="ConsoleApplication1.TwoRepository" /> </container> </unity> </configuration>

Solicitud

Esta es la Raíz de Composición .

public class Program { static void Main() { UnityContainer container = new UnityContainer(); var res = container.LoadConfiguration(); Worker worker = res.Resolve<Worker>(); Console.WriteLine(worker.DoOne()); Console.WriteLine(worker.DoTwo()); Console.Read(); } }

La salida como se espera es:

One Two


Podría considerar usar un servicio agregado que agrupe varios otros servicios, pero también debe mirar cuidadosamente para ver si su MyClass está tratando de hacer demasiado ; tener una gran cantidad de dependencias puede ser una indicación de eso.