Castle Windsor: How to specify a constructor param

2019-02-04 23:15发布

Say I have the following class

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

I can register an instance of it with castle windsor via xml as follows

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

How would I go about doing the exact same thing but in code? (Notice, the constructor parameter)

5条回答
萌系小妹纸
2楼-- · 2019-02-04 23:23

You need to pass in an IDictionary when you ask the container for the instance.

You'd use this Resolve overload of the IWindsorContainer:

T Resolve<T>(IDictionary arguments)

or the non generic one:

object Resolve(Type service, IDictionary arguments)

So, for example: (assuming container is an IWindsorContainer)

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

Note that the key values in the dictionary are case sensitive.

查看更多
够拽才男人
3楼-- · 2019-02-04 23:25

Edit: Used the answers below code with the Fluent Interface :)

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

    }
}
查看更多
手持菜刀,她持情操
4楼-- · 2019-02-04 23:28

You can use the AddComponentWithProperties method of the IWindsorContainer interface to register a service with extended properties.

Below is a 'working' sample of doing this with an NUnit Unit Test.

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

    }
}
查看更多
smile是对你的礼貌
5楼-- · 2019-02-04 23:32

Have you considered using Binsor to configure your container? Rather than verbose and clumsy XML you can configure Windsor using a Boo based DSL. Here's what your config will look like:

component IMyComponent, MyComponent:
   start_at = 1

The advantage is that you have a malleable config file but avoid the problems with XML. Also you don't have to recompile to change your config as you would if you configured the container in code.

There's also plenty of helper methods that enable zero friction configuration:

  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

You can get started with it here.

查看更多
男人必须洒脱
6楼-- · 2019-02-04 23:34

Try this

int start_at = 1; 
container.Register(Component.For().DependsOn(dependency: Dependency.OnValue(start_at)));
查看更多
登录 后发表回答