鉴于此XML配置(有效)
<component type="X.Y.Z.ActivityService, X.Y.Z.Services" id="X.Y.Z.ActivityService" lifestyle="transient">
<parameters>
<Listeners>
<array>
<item>${DefaultActivityListener}</item>
</array>
</Listeners>
</parameters>
</component>
<component type="X.Y.Z.DefaultActivityListener, X.Y.Z.Services" id="DefaultActivityListener" lifestyle="transient" />
我已经转换为使用如下的流畅API(这不起作用):
Container.Register(
Component.For<X.Y.Z.ActivityService>()
.ServiceOverrides(
ServiceOverride.ForKey("Listeners").Eq(typeof(X.Y.Z.DefaultActivityListener).Name))
.LifeStyle.Transient
);
Container.Register(
Component.For<X.Y.Z.DefaultActivityListener>()
.Named("DefaultActivityListener")
.LifeStyle.Transient
);
当我现在尝试解析X.Y.Z.ActivityService
Windsor的实例时,会在NotImplementedException
中引发Castle.MicroKernel.SubSystems.Conversion.ArrayConverter.PerformConversion(String, Type)
。
PerformConversion方法的实现是:
public override object PerformConversion(String value, Type targetType)
{
throw new NotImplementedException();
}
我应该补充一点,如果我删除ServiceOverrides
调用,则所有操作都符合预期。所以我在连接Listeners参数的方式上有一些特别的错误。顺便说一下,监听器是一个属性,而不是构造函数参数。
看到XML配置按预期工作,我如何最好地使用流畅的API(没有实现PerformConversion方法)以获得相同的结果?
我正在使用版本2.0。
修改
我会将问题扩展到如何在代码中实现此配置,无论是否使用流畅的API。
更新
如果您尝试将单个元素分配给数组属性,则会出现问题。下面提供单元测试来说明问题。
namespace Components
{
public class A
{
public I[] I { get; set; }
}
public interface I
{
string Name { get; }
}
public class B : I
{
public string Name { get { return "B"; } }
}
public class C : I
{
public string Name { get { return "C"; } }
}
}
[TestMethod]
public void ArrayPropertyTestApi()
{
//PASSES
using (Castle.Windsor.WindsorContainer container = new Castle.Windsor.WindsorContainer())
{
container.Register(Component.For<Components.A>().ServiceOverrides(ServiceOverride.ForKey("I").Eq(typeof(Components.B).FullName, typeof(Components.C).FullName)));
container.Register(Component.For<Components.B>());
container.Register(Component.For<Components.C>());
Components.A svc = container.Resolve<Components.A>();
Assert.IsTrue(svc.I.Length == 2);
Assert.IsTrue(svc.I[0].Name == "B");
Assert.IsTrue(svc.I[1].Name == "C");
}
}
[TestMethod]
public void ArrayPropertyTestApi2()
{
//FAILS
using (Castle.Windsor.WindsorContainer container = new Castle.Windsor.WindsorContainer())
{
container.Register(Component.For<Components.A>().ServiceOverrides(ServiceOverride.ForKey("I").Eq(typeof(Components.B).FullName)));
container.Register(Component.For<Components.B>());
container.Register(Component.For<Components.C>());
Components.A svc = container.Resolve<Components.A>(); //Throws NotImplementedException
Assert.IsTrue(svc.I.Length == 1);
Assert.IsTrue(svc.I[0].Name == "B");
}
}
问题仍然存在。
感谢。
答案 0 :(得分:3)
[TestFixture]
public class WindsorTests {
[Test]
public void ArrayConfig() {
var container = new WindsorContainer();
container.Register(Component.For<Listener>().Named("listener"));
container.Register(Component.For<ActivityService>()
.ServiceOverrides(ServiceOverride.ForKey("listeners").Eq(new[] {"listener"})));
var service = container.Resolve<ActivityService>();
Assert.AreEqual(1, service.Listeners.Length);
}
}
public class Listener {}
public class ActivityService {
public Listener[] Listeners { get; set; }
}
这里的关键部分是new[] {"listener"}
。 MicroKernel需要知道参数侦听器是一个数组,如果只传递“listener”,它会假定参数是标量并抛出,因为它无法将标量转换为数组。