Pregunta

Recientemente comencé a usar un contenedor IoC por primera vez, pero No estoy educado en las mejores prácticas para su uso. Más específicamente, estoy usando Unity en un proyecto de C # .NET, y comencé a usarlo porque venía con Prism .

Utilizo el contenedor para resolver el " nivel superior " objetos, y obtienen los objetos correctos inyectados en función del contenedor. Sin embargo, no puedo ver claramente la mejor práctica cuando tengo un objeto con niños y niños de niños, y necesito algunos datos del contenedor de IoC hasta el fondo, pero no en el medio. ¿Cómo organizaría normalmente el uso del contenedor IoC?

Inicialmente, creo que pasaría el contenedor a donde sea necesario en lugar de extraer los datos necesarios del contenedor en el nivel superior y pasar estos datos. Pero nuevamente, tengo problemas cuando alcanzo objetos que toman otros datos específicos además de las interfaces inyectadas, y prefiero no inyectarlos a través de propiedades o métodos init después de resolver el objeto.

Espero que esto haya sido lo suficientemente claro, pero veamos un ejemplo ficticio (y un poco estúpido ...).

class Employee
{
    private ICommands _commands; 
    priate List<Customer> _customers = new List<Customer>(); 
    public Employee(ICommands commands)
    {
        _commands = commands; 
    }
    public void AddCustomer(string customerName)
    {
        var customer = new Customer(customerName, _commands); 
        _customers.Add(customer); 
    }
}

class Customer 
{
    private string _name; 
    private ICommands _commands; 
    priate List<Case> _cases = new List<Case>(); 
    public Customer(string, name, ICommands commands)
    {
        _name = name; 
        _commands = commands; 
    }
    public void AddCase()
    {
        var case = new Case(_commands); 
        _cases.Add(case); 
    }
}

class Case    {
    private ICommands _commands; 
    public Customer(ICommands commands)
    {
        _commands = commands; 
    }
    public void TriggerCommands()
    {
        _command.TriggerSomething(); 
    }
}

Entonces, este ejemplo realmente no tiene mucho sentido, pero la esencia es la misma que necesito hacer. Tengo algunos comandos de aplicación que paso por la línea a través de mis clases de ViewModel, porque algunos de ellos necesitan poder activar comandos para mostrar algo. También tengo un almacenamiento común, etc., que puede ser necesario para algunas clases, pero actualmente se transfieren y se almacenan en clases medias. Con solo comandos no es gran cosa si almacena comandos o contenedor, pero ¿uno de ellos en un uso típico de IoC pasará el contenedor IoC en su lugar, y usará esto para resolver objetos en la línea? ¿Y qué hay de los datos específicos como el nombre del cliente? ¿No puede simplemente pasar esto en la Resolución (), por lo que necesita inyectarlo después?

Lo siento, esto fue tan breve como pude hacerlo. No requerirá respuestas de la misma longitud ;-) .. Solo; ¿Cuál es la mejor práctica de hacer cosas como esta con los contenedores IoC?

¿Fue útil?

Solución

No estoy seguro de entender tu pregunta. Pero no creo que debas pasar el contenedor. Es mucho más fácil crear una clase de contenedor para el contenedor. Por ejemplo:

public class IoCContainer
{
  private static ContainerType = null;

  public static ContainerType Instance 
  {
    get 
    {
      if (_container == null)
      {
        string configFileName = ConfigurationManager.AppSettings[ConfigFileAppSettingName];
        _container = new WindsorContainer(new XmlInterpreter(configFileName));
      }

      return _container;
    }
  }
}

Ahora llamas a esto en todas partes en tu código.

IoCContainer.Instance.Resolve<IAwesomeService>(); 

¿Esto te ayuda?

Otros consejos

No estoy seguro de si esto responde a tu pregunta, pero diría que una buena manera de actuar en una aplicación utilizando el contenedor de Unity (también aplicable a otros motores IoC) es:

  • Diseña tus clases para que todos los Se especifican las dependencias requeridas. en el constructor. De esta manera usted no es necesario tratar explícitamente con Unidad a menos que necesite crear nuevos objetos.
  • Si necesitas crear nuevos objetos Dentro de tus clases, pasa la Unidad. contenedor en sí mismo en el constructor también (como una referencia a IUnityContainer ), y crea todos los nuevos instancias de objetos utilizando el Resolver método. Incluso para objetos que no están Registrado y no tener dependencias, El contenedor te dará una adecuada instancia, y luego puede decidir registrar tipos que no estaban registrados previamente, sin cambiar el código de cliente.
  • En cuanto a pasar valores explícitos a objetos resueltos, puede especificar miembros de inyección concretos al registrar tipos (consulte el parámetro InjectionMembers en la clase RegisterType ).

Parece que necesita declarar fábricas para sus entidades. Resuelva las fábricas a través de la inyección del constructor y pase los valores de los datos a través del método Crear. Todas las demás dependencias se deben resolver a través del constructor de fábrica.

Consulte esta respuesta.

Definiría una clase estática IoC, que se puede inicializar con un contenedor particular e implementar métodos como Resolver, Resolver (...), que a su vez delegan el trabajo real a la instancia del contenedor (almacenará esto instancia en un campo o propiedad). De esta manera, no tiene que pasar nada, solo use

IoC.Resolve<SomeType>();

en cualquier parte de tu código.

Con respecto a los datos específicos: algunos contenedores tomarán un parámetro y se resolverán dependiendo de este parámetro (Autofac tiene este tipo de característica). O siempre puede crear una clase de fábrica que tendrá un método que acepte un conjunto de parámetros (como el nombre del cliente) y devuelva una instancia de objeto correspondiente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top