dependency-injection - tipos - spring tool suite tutorial español
Crear objetos con dependencias-inyección de dependencia (3)
Digamos que tenemos clase:
public class WithDependencies
{
public WithDependencies(IAmDependencyOne first, IAmDependencyTwo second)
// ...
}
Ahora la pregunta. ¿Cómo se crean objetos de la clase WithDependencies en una aplicación? Sé que hay muchas formas.
new WithDependencies(new DependencyOne(), new DependencyTwo());
new WithDependencies(IoC.Resolve(IDependencyOne), IoC.Resolve(IDependencyTwo());
// register IDependencyOne, IDependencyTwo implementations at app start
IoC.Resolve(WithDependencies);
// register IDependencyOne, IDependencyTwo implementations at app start
// isolate ourselves from concrete IoC Container
MyCustomWithDependenciesFactory.Create();
y así...
¿Cuál crees que es la forma de hacerlo?
Editar:
Como no recibo las respuestas o no las entiendo, intentaré volver a preguntar. Digamos que en algún evento (botón, temporizador, lo que sea) necesito un nuevo objeto WithDependencies (). ¿Cómo lo creo? Supongamos que el contenedor IoC ya está configurado.
A veces trato de deshacerme de las fábricas o al menos no dependo directamente de ellas, por lo que la Inyección de Dependencia (sin fábricas) es útil por supuesto.
Por lo tanto, utilizo Google Juice, porque es un pequeño marco usando Anotaciones de Java y puede cambiar rápidamente sus inyecciones / dependencias. Solo échale un vistazo:
Depende del contexto, por lo que es imposible proporcionar una sola respuesta. Conceptualmente , harías algo así de la raíz de composición :
var wd = new WithDependencies(new DependencyOne(), new DependencyTwo());
Sin embargo, incluso en ausencia de un Contenedor DI, el código anterior no siempre es inequívocamente la respuesta correcta. En algunos casos, es posible que desee compartir la misma dependencia entre varios consumidores, como esta:
var dep1 = new DependencyOne();
var wd = new WithDependencies(dep1, new DependencyTwo());
var another = AnotherWithDependencies(dep1, new DependencyThree());
En otros casos, es posible que no desee compartir dependencias, en cuyo caso la primera opción es más correcta.
Este es solo un pequeño vistazo de una dimensión completa de DI relacionada con Lifetime Management . Muchos DI Containers pueden encargarse de eso, lo cual es un excelente argumento para preferir un DI Container sobre el Poor Man''s DI.
Una vez que comience a usar un Contenedor DI, debe seguir el patrón Registrar Resolver Release al resolver los tipos, permitiendo que el Auto-cableado se encargue de la composición real:
var wd = container.Resolve<WithDependencies>();
El ejemplo anterior supone que el contenedor ya está configurado correctamente.
Si necesita crear una dependencia que tenga sus propias dependencias, puede A) hacerlo usted mismo o B) pedirle a otra persona que lo haga por usted. La opción A niega los beneficios de la inyección de dependencia (desacoplamiento, etc.), por lo que yo diría que la opción B es un mejor punto de partida. Ahora, hemos elegido utilizar el patrón de fábrica, sin importar si se trata de un localizador de servicios (es decir, IoC.Resolve
), una fábrica estática o una fábrica de instancias. El punto es que hemos delegado esa responsabilidad a una autoridad externa.
Hay una serie de concesiones necesarias para los accessors estáticos. ( Los revisé en otra respuesta , así que no los repetiré aquí). Para evitar introducir una dependencia en la infraestructura o el contenedor, una opción sólida es aceptar una fábrica para crear WithDependencies
cuando necesitamos una instancia en alguna parte. más:
public class NeedsWithDependencies
{
private readonly IWithDependenciesFactory _withDependenciesFactory;
public NeedsWithDependencies(IWithDependenciesFactory withDependenciesFactory)
{
_withDependenciesFactory = withDependenciesFactory;
}
public void Foo()
{
var withDependencies = _withDependenciesFactory.Create();
...Use the instance...
}
}
A continuación, podemos crear una implementación específica de contenedor de la fábrica:
public class WithDependenciesFactory : IWithDependenciesFactory
{
private readonly IContainer _container;
public WithDependenciesFactory(IContainer container)
{
_container = container
}
public WithDependencies Create()
{
return _container.Resolve<WithDependencies>();
}
}
Ahora NeedsWithDependencies
está completamente aislado de cualquier conocimiento de cómo se crea WithDependencies
; también expone todas sus dependencias en su constructor, en lugar de ocultar dependencias en los accesos estáticos, lo que facilita su reutilización y prueba.
Definir todas esas fábricas puede ser un poco engorroso, sin embargo. Me gusta el tipo de relación de fábrica de Autofac , que detectará los parámetros de la forma Func<TDependency>
e inyectará automáticamente una función que cumple la misma función que la fábrica codificada a mano anterior:
public class NeedsWithDependencies
{
private readonly Func<WithDependencies> _withDependenciesFactory;
public NeedsWithDependencies(Func<WithDependencies> withDependenciesFactory)
{
_withDependenciesFactory = withDependenciesFactory;
}
public void Foo()
{
var withDependencies = _withDependenciesFactory();
...Use the instance...
}
}
También funciona muy bien con los parámetros de tiempo de ejecución:
public class NeedsWithDependencies
{
private readonly Func<int, WithDependencies> _withDependenciesFactory;
public NeedsWithDependencies(Func<int, WithDependencies> withDependenciesFactory)
{
_withDependenciesFactory = withDependenciesFactory;
}
public void Foo(int x)
{
var withDependencies = _withDependenciesFactory(x);
...Use the instance...
}
}