Castle Windsor: Comment spécifier un paramètre constructeur à partir de code?

StackOverflow https://stackoverflow.com/questions/87812

  •  01-07-2019
  •  | 
  •  

Question

Disons que j'ai la classe suivante

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

Je peux enregistrer une instance de Castle Windsor via XML comme suit

<component id="sample"  service="NS.IMyComponent, WindsorSample" type="NS.MyComponent, WindsorSample">  
  <parameters>  
    <start_at>1</start_at >  
  </parameters>  
</component>  

Comment pourrais-je faire exactement la même chose mais en code? (Remarquez, le paramètre constructeur)

Était-ce utile?

La solution

Édition: utilisé le code de réponse ci-dessous avec l’interface Fluent:)

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));
        }

    }
}

Autres conseils

Essayez ceci

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

Avez-vous envisagé d’utiliser Binsor pour configurer votre conteneur? Plutôt que de XML verbeux et maladroit, vous pouvez configurer Windsor à l'aide d'un DSL basé sur Boo. Voici à quoi ressemblera votre configuration:

component IMyComponent, MyComponent:
   start_at = 1

L’avantage est que vous disposez d’un fichier de configuration malléable tout en évitant les problèmes liés à XML. De plus, vous n'avez pas besoin de recompiler pour changer votre configuration comme vous le feriez si vous configuriez le conteneur en code.

Il existe également de nombreuses méthodes d'assistance permettant une configuration sans frottement:

  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

Vous pouvez commencer à l'utiliser avec ici .

Vous devez passer un IDictionary lorsque vous demandez le conteneur pour l'instance.

Vous utiliseriez cette surcharge de résolution du conteneur IWindsorContainer:

T Resolve<T>(IDictionary arguments)

ou le non générique:

object Resolve(Type service, IDictionary arguments)

Ainsi, par exemple: (en supposant que le conteneur est un conteneur IWindsorContainer)

IDictionary<string, object> values = new Dictionary<string, object>();
values["start_at"] = 1;
container.Resolve<IMyComponent>(values);

Notez que les valeurs de clé du dictionnaire sont sensibles à la casse.

Vous pouvez utiliser une classe de configuration pour lire le fichier app.config. Puis enregistrez-le et demandez à windsor de l’utiliser pour sa dépendance. Idéalement, MyConfiguration utiliserait une interface.

public class MyConfiguration
{
    public long CacheSize { get; }

    public MyConfiguration()
    {
        CacheSize = ConfigurationManager.AppSettings["cachesize"].ToLong();
    }
}



container.Register(Component.For<MyConfiguration>().ImplementedBy<MyConfiguration>());

container.Register(Component.For<MostRecentlyUsedSet<long>>()
.ImplementedBy<MostRecentlyUsedSet<long>>().
DependsOn(Dependency.OnValue("size", container.Resolve<MyConfiguration>().CacheSize))
.LifestyleSingleton());

Vous pouvez utiliser la méthode AddComponentWithProperties de l'interface IWindsorContainer pour inscrire un service avec des propriétés étendues.

Vous trouverez ci-dessous un exemple concret de cette opération avec un test unitaire 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));
        }

    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top