2008-09-17 68 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))); 
相關問題