2008-09-17 13 views
11

Decir que tengo la siguiente claseCastle Windsor: ¿Cómo especificar un parámetro constructor a partir del código?

MyComponent : IMyComponent { 
    public MyComponent(int start_at) {...} 
} 

puedo registrar una instancia de la misma con el castillo de 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 ir haciendo exactamente lo mismo pero en código? (Tenga en cuenta que el parámetro constructor)

Respuesta

15

Modificar: Se usa las respuestas a continuación código 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)); 
     } 

    } 
} 
+1

¿Funciona esta solución si el parámetro es de tipo complejo, como otro IMyComponent? – flipdoubt

+0

Si la dependencia está en el contenedor, se resolverá automáticamente –

+0

Me encantaría usar una interfaz fluida, sin embargo, descargar castle source, nant (que nunca he usado antes) y calcularlo todo es un poco más –

0

Debe enviar un IDictionary cuando solicite el contenedor para la instancia.

tendrá que utilizar esta sobrecarga de determinación de la IWindsorContainer:

T Resolve<T>(IDictionary arguments) 

o el genérico no uno:

object Resolve(Type service, IDictionary arguments) 

Así, por ejemplo: (suponiendo 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.

+0

Lo sentimos Gareth, pero esto no es lo mismo que el código XML que he publicado. Aquí el usuario necesita conocer el parámetro, mientras que el XML proporciona un valor predeterminado. –

+0

+1 para resolver un problema diferente: instanciar un objeto con un parámetro pasado en tiempo de ejecución. –

-1

Usted puede utilizar el método de la interfaz AddComponentWithProperties IWindsorContainer 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)); 
     } 

    } 
} 
+0

Just He intentado esto, no funciona: No se pudo resolver la dependencia no opcional para 'concreto' (WindsorSample.MyComponent). El parámetro 'start_at' mecanografía 'System.Int32' –

1

¿Ha considerado utilizar Binsor para configurar su contenedor? En lugar de XML detallado y torpe, puede configurar Windsor usando un DSL basado en Boo. Esto es lo que su configuración se verá así:

component IMyComponent, MyComponent: 
    start_at = 1 

La ventaja es que usted tiene un archivo de configuración maleable, pero evitar 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 un montón de métodos auxiliares que permiten la configuración rápida de la 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 

Puede empezar con él here.

+0

Cuando consigo más de 3 segundos para mí, planeo echarle un vistazo. También es importante para mí que esto sea algo que pueda cambiar sin volver a compilar, ya que planeo activar/desactivar los interceptores para depurar aplicaciones en el campo –

2

probar este

int start_at = 1; 
container.Register(Component.For().DependsOn(dependency: Dependency.OnValue(start_at))); 
+1

, ¿me pueden explicar un poco más? –

+0

Este es un intento honesto de respuesta y, por lo tanto, no debe señalarse como una respuesta. Si no te gusta la respuesta, debes declinarla, no marcarla. – ArtOfWarfare

Cuestiones relacionadas