我正在授予kellyb這個傑出的例子的答案。在調查過程中,使用Castle.Windsor 3.2.1,我發現至少有兩個在「解析」方法中傳遞值的原因。
- 爲了滿足本徵型的依賴關係,例如字符串或整數在 通過使用「解析」方法的解析對象 - 如在kellyb的實施例中描述 。
- 幫助城堡識別選擇哪個具體實現。
幫助說明兩種用法我正在詳細說明kellyb上面提供的示例。
梗概 - 或測試條件
假設有稱爲IFoo的一個接口和從該接口稱爲Foo和Bar導出兩個具體實現。一個名爲Baz的類被定義,但不是從任何東西中派生出來的。假設Foo需要兩個字符串,但Bar需要一個Baz。
接口的IFoo定義
namespace CastleTest
{
public interface IFoo
{
}
}
類Foo定義
namespace CastleTest
{
public class Foo : IFoo
{
private readonly string _arg1;
private readonly string _arg2;
public Foo(string arg1, string arg2)
{
_arg1 = arg1;
_arg2 = arg2;
}
public override string ToString()
{
return string.Format("{0} {1}", _arg1, _arg2);
}
}
}
類欄定義
namespace CastleTest
{
class Bar : IFoo
{
private Baz baz;
public Bar(Baz baz)
{
this.baz = baz;
}
public override string ToString()
{
return string.Format("I am Bar. Baz = {0}", baz);
}
}
}
類巴茲定義
namespace CastleTest
{
public class Baz
{
public override string ToString()
{
return "I am baz.";
}
}
}
測試(輥筒式,拜託了!)
kellyb的例子測試表明,如果沒有提供ARGS期望一個失敗的斷言。 kellyb的例子沒有註冊多個實現。我的例子有多個實現註冊,並根據哪些被標記爲默認,這個斷言可能會或可能不會失敗。例如,如果名爲「AFooNamedFoo」的具體實現標記爲default,則assert成功完成 - 也就是說IFoo作爲Foo的解析確實需要定義args。如果名爲「AFooNamedBar」的具體實現標記爲default,則斷言失敗 - 也就是說IFoo作爲Bar的解析不需要定義參數,因爲它對Baz的依賴關係已經被註冊(在我的示例中,where多個具體的實現被註冊)。出於這個原因,我已經在我的例子中評論了斷言。
using Castle.Core;
using Castle.MicroKernel.Handlers;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using NUnit.Framework;
namespace CastleTest
{
[TestFixture]
public class ArgsIdentifyConcreteImplementation
{
[Test]
public void WhenSendingArgsInResolveMethodTheyAreUsedToIdentifyConcreteImplementation()
{
IWindsorContainer container = new WindsorContainer();
container.Register(Component.For<IFoo>().ImplementedBy<Foo>().LifeStyle.Is(LifestyleType.Transient).Named("AFooNamedFoo"));
container.Register(Component.For<IFoo>().ImplementedBy<Bar>().LifeStyle.Is(LifestyleType.Transient).Named("AFooNamedBar").IsDefault());
container.Register(Component.For<Baz>().ImplementedBy<Baz>().LifeStyle.Is(LifestyleType.Transient));
// THIS ASSERT FAILS IF AFooNamedBar IS DEFAULT, BUT
// WORKS IF AFooNamedFoo IS DEFAULT
//Assert.Throws<HandlerException>(() => container.Resolve<IFoo>());
// RESOLVE A FOO
IFoo foo = container.Resolve<IFoo>("AFooNamedFoo", new { arg1 = "hello", arg2 = "world" });
Assert.That(foo, Is.InstanceOf<Foo>());
Assert.That(foo.ToString(), Is.EqualTo("hello world"));
// RESOLVE A BAR
IFoo bar = container.Resolve<IFoo>("AFooNamedBar");
Assert.That(bar, Is.InstanceOf<Bar>());
Assert.That(bar.ToString(), Is.EqualTo("I am Bar. Baz = I am baz."));
}
}
}
結論
看看上面的測試,Foo對象的分辨率必須在「解決」的方法通過兩件事情 - 在實現的名稱,並作爲額外的字符串依賴IDictionary對象。 Bar對象的解析有一件事在「解析」方法中傳遞 - 實現的名稱。
您是否說過任何值已通過在解析方法中將用於滿足正在解析的對象的構造函數參數?我發現在Castle Windsor 3中,傳入的值有助於castle識別使用哪個具體實現(假設註冊組件已經在名稱方法中定義了一個值)。這與你的建議完全不同 - 並不是說你不正確,因爲可能有多種用途。這是我試圖確定的。您是否嘗試過使用此提供的值來派生具體的實現? – barrypicker
字典,匿名類型和參數參數重載是我在上面顯示的內容。 「key」參數重載用於解決按鍵指定註冊。在最近版本的Windsor中,爲註冊分配一個密鑰是可選的(如果每個服務類型有多個註冊,密鑰仍然是必需的)。重讀你的問題後,你聽起來像需要爲註冊指定一個鍵,然後在Resolve方法上傳遞一個鍵... – kellyb
或者使用像IHandlerSelector這樣的東西來處理分辨率。這取決於你的架構和我的運行時知道哪些應該解決......但你應該儘可能避免從容器中「拉」。 – kellyb