tutorial - castle.net core
Castle Windsor: ¿Cómo especificar un parámetro constructor a partir del código? (5)
Prueba esto
int start_at = 1;
container.Register(Component.For().DependsOn(dependency: Dependency.OnValue(start_at)));
Digamos que tengo la siguiente clase
MyComponent : IMyComponent {
public MyComponent(int start_at) {...}
}
Puedo registrar una instancia de esto con castle windsor a través de xml de la siguiente manera
<component id="sample" service="NS.IMyComponent, WindsorSample" type="NS.MyComponent, WindsorSample">
<parameters>
<start_at>1</start_at >
</parameters>
</component>
¿Cómo voy a hacer exactamente lo mismo pero en código? (Aviso, el parámetro constructor)
Necesitará pasar un IDictionary cuando solicite el contenedor para la instancia.
Utilizarías esta sobrecarga de Resolve del IWindsorContainer:
T Resolve<T>(IDictionary arguments)
o el no genérico:
object Resolve(Type service, IDictionary arguments)
Entonces, por ejemplo: (asumiendo que el contenedor es un IWindsorContainer)
IDictionary<string, object> values = new Dictionary<string, object>();
values["start_at"] = 1;
container.Resolve<IMyComponent>(values);
Tenga en cuenta que los valores clave en el diccionario distinguen entre mayúsculas y minúsculas.
Editar: usé el código de las respuestas a continuación con la interfaz fluida :)
namespace WindsorSample
{
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
public class MyComponent : IMyComponent
{
public MyComponent(int start_at)
{
this.Value = start_at;
}
public int Value { get; private set; }
}
public interface IMyComponent
{
int Value { get; }
}
[TestFixture]
public class ConcreteImplFixture
{
[Test]
void ResolvingConcreteImplShouldInitialiseValue()
{
IWindsorContainer container = new WindsorContainer();
container.Register(
Component.For<IMyComponent>()
.ImplementedBy<MyComponent>()
.Parameters(Parameter.ForKey("start_at").Eq("1")));
Assert.That(container.Resolve<IMyComponent>().Value, Is.EqualTo(1));
}
}
}
Puede usar el método AddComponentWithProperties de la interfaz IWindsorContainer para registrar un servicio con propiedades extendidas.
A continuación se muestra una muestra de "trabajo" de hacer esto con una prueba de unidad NUnit.
namespace WindsorSample
{
public class MyComponent : IMyComponent
{
public MyComponent(int start_at)
{
this.Value = start_at;
}
public int Value { get; private set; }
}
public interface IMyComponent
{
int Value { get; }
}
[TestFixture]
public class ConcreteImplFixture
{
[Test]
void ResolvingConcreteImplShouldInitialiseValue()
{
IWindsorContainer container = new WindsorContainer();
IDictionary parameters = new Hashtable {{"start_at", 1}};
container.AddComponentWithProperties("concrete", typeof(IMyComponent), typeof(MyComponent), parameters);
IMyComponent resolvedComp = container.Resolve<IMyComponent>();
Assert.That(resolvedComp.Value, Is.EqualTo(1));
}
}
}
¿Ha considerado usar Binsor para configurar su contenedor? En lugar de XML detallado y torpe, puede configurar Windsor usando un DSL basado en Boo. Así es como se verá tu configuración:
component IMyComponent, MyComponent:
start_at = 1
La ventaja es que tiene un archivo de configuración maleable pero evita los problemas con XML. Además, no tiene que volver a compilar para cambiar su configuración como lo haría si configurara el contenedor en el código.
También hay muchos métodos de ayuda que permiten la configuración de cero fricción:
for type in Assembly.Load("MyApp").GetTypes():
continue unless type.NameSpace == "MyApp.Services"
continue if type.IsInterface or type.IsAbstract or type.GetInterfaces().Length == 0
component type.GetInterfaces()[0], type
Puedes comenzar con esto aquí .