我将答案授予 kellyb 的真棒示例。在调查过程中,使用 Castle.Windsor 3.2.1,我发现至少有两个原因需要在“resolve”方法中传递值。
- 满足内在的类型依赖,例如字符串或整数
使用“Resolve”方法解析的对象 - 如
在 kellyb 的示例中进行了描述。
- 帮助 Castle 确定要选择的具体实现。
为了帮助说明这两种用途,我正在详细说明上面由 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);
}
}
}
类 Baz 定义
namespace CastleTest
{
public class Baz
{
public override string ToString()
{
return "I am baz.";
}
}
}
测试(请打鼓!)
kellyb 的示例测试显示了一个断言,如果未提供 args,则该断言会失败。 kellyb 的示例没有注册多个实现。我的示例注册了多个实现,并且根据哪个被标记为默认值,此断言可能会失败,也可能不会失败。例如,如果名为“AFooNamedFoo”的具体实现被标记为默认,则断言成功完成 - 也就是说,将 IFoo 解析为 Foo 确实需要定义 args。如果名为“AFooNamedBar”的具体实现被标记为默认值,则断言失败——也就是说,将 IFoo 解析为 Bar 不需要定义 args,因为它对 Baz 的依赖已经注册(在我的示例中注册了多个具体实现)。因此,我在示例中注释掉了断言。
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 对象的解析在“resolve”方法中传递了两件事——实现的名称,以及作为 IDictionary 对象的附加字符串依赖项。 Bar 对象的解析在“resolve”方法中传递了一件事——实现的名称。