2008-09-17 72 views
11

说我有下面的类Castle Windsor:如何从代码指定构造函数参数?

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

我可以它与温莎城堡通过XML如下

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

我怎么会去这样做同样的事情,但在代码注册一个实例? (注意,构造函数参数)

回答

15

编辑:使用下面的代码的答案用流利的接口:)

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

如果参数是复杂类型(如另一个IMyComponent),此解决方案是否工作? – flipdoubt 2008-09-18 15:15:34

+0

如果依赖关系在容器中,它将自动解析 – 2008-09-18 15:22:13

+0

我喜欢使用流畅的界面,但是下载castle源码,nant(我以前从未使用过)并且全部搞清楚了这一点有点多 – 2008-09-23 14:08:32

0

当你问容器的实例时,你需要传入一个IDictionary。

你会使用IWindsorContainer这个解决超载:

T Resolve<T>(IDictionary arguments) 

还是非一般的一个:

object Resolve(Type service, IDictionary arguments) 

因此,例如:(假设容器是IWindsorContainer)

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

请注意,字典中的键值区分大小写。

+0

对不起加雷,但这是不一样的东西,因为我张贴的XML。在这里,参数需要被解析器知道,而有问题的XML提供了一个默认值。 – 2008-09-17 21:50:57

+0

+1用于解决不同的问题 - 使用在运行时传递的参数实例化对象。 – 2012-03-13 08:25:22

-1

可以使用IWindsorContainer接口的AddComponentWithProperties方法注册一个带有扩展属性的服务。

下面是一个使用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)); 
     } 

    } 
} 
1

您是否考虑过使用Binsor来配置您的容器?您可以使用基于Boo的DSL配置Windsor,而不是冗长而笨拙的XML。这里是你的配置将是什么样子:

component IMyComponent, MyComponent: 
    start_at = 1 

的好处是,你有一个可延展的配置文件,但避免与XML的问题。此外,您不必重新编译即可更改配置,就像在代码中配置容器一样。

中也有很多的辅助方法,使零摩擦的配置:

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 

你可以得到它开始here

2

试试这个

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