inversion-of-control - framework - ioc container c#
¿Cómo le paso un parámetro al constructor utilizando Simple Injector? (3)
Lo anterior funcionará si su constructor no tiene otras dependencias (o si desea resolver estas dependencias manualmente). Si tienes el siguiente escenario a pesar de que se cae:
public class Test : ITest
{
private IFoo _foo;
public Test(string parameter, IFoo foo)
{
_foo = foo;
....
}
}
Ahora no solo tienes que inyectar manualmente la cadena sino también Foo
. Así que ahora no estás usando la inyección de dependencia (en realidad). También el estado del inyector simple:
Simple Injector no permite inyectar tipos primitivos (como enteros y cadenas) en constructores.
Mi lectura de esto es que están diciendo "no hagas esto".
Puntos de extensibilidad
Otra opción aquí es usar "Puntos de extensibilidad" para este escenario .
Para hacer esto necesita abstraer sus elementos codificados de sus elementos inyectados:
public class Test : ITest
{
private IFoo _foo;
public Test(IFoo foo)
{
_foo = foo;
....
}
public void Init(string parameter)
{
}
}
Ahora puede inyectar sus dependencias y sus elementos codificados:
_container.Register<ITest, Test>();
_container.RegisterInitializer<Test>(instance => {instance.Init("MyValue");});
Si ahora agrega otra dependencia, su inyección ahora funcionará sin que tenga que actualizar la configuración, es decir, su código aún está bien desacoplado:
public class Test : ITest
{
private IFoo _foo;
private IBar _bar;
public Test(IFoo foo, IBar bar)
{
_foo = foo;
_bar = bar;
....
}
public void Init(string parameter)
{
}
}
¿Simple Injector le permite pasar parámetros al constructor cuando resuelve? Me gustaría saber si estos dos marcos hacen lo que ambos hacen ResolverOverride o DependencyOverride de Unity.
Probablemente la opción más fácil con Simple Injector es registrarse con un delegado
[Test]
public void Test1()
{
Container container = new Container();
container.Register<IClassWithParameter>(() => new ClassWithParameter("SomeValue"));
var result = container.GetInstance<IClassWithParameter>();
}
public interface IClassWithParameter { }
public class ClassWithParameter : IClassWithParameter
{
public ClassWithParameter(string parameter)
{
}
}
Una opción avanzada para inyectar dependencias primitivas se detalla here
Sospecho que esta pregunta es acerca de pasar valores primitivos al constructor en el momento en que el servicio se resuelve realmente.
Vamos a configurar una clase de prueba simple:
public interface IFoo
{
}
public class Foo : IFoo
{
public Foo(string value)
{
}
}
La clase Foo toma un argumento de cadena que nos gustaría proporcionar al resolver el servicio IFoo.
var container = new ServiceContainer();
container.Register<string, IFoo>((factory, value) => new Foo(value));
var firstFoo = container.GetInstance<string, IFoo>("SomeValue");
var secondFoo = container.GetInstance<string, IFoo>("AnotherValue");
Si queremos poder crear nuevas instancias de la clase Foo sin usar el contenedor directamente, simplemente podemos inyectar una función de delegado.
public interface IBar { }
public class Bar : IBar
{
public Bar(Func<string, IFoo> fooFactory)
{
var firstFoo = fooFactory("SomeValue");
var secondFoo = fooFactory("AnotherValue");
}
}
La "raíz de composición" ahora se ve así:
var container = new ServiceContainer();
container.Register<string, IFoo>((factory, value) => new Foo(value));
container.Register<IBar, Bar>();
var bar = container.GetInstance<IBar>();
Si la pregunta es sobre pasar un valor primitivo "estático" al contructor, esto se hace simplemente registrando un delegado de fábrica como este.
var container = new ServiceContainer();
container.Register<IFoo>((factory) => new Foo("SomeValue"));
var firstInstance = container.GetInstance<IFoo>();
var secondInstance = container.GetInstance<IFoo>();
La diferencia es que este enfoque no le permite pasar un valor en el momento de la resolución. El valor se especifica estáticamente en el momento del registro.