我的域名看起来像这样:
public interface IParent{ IChild[] Children { get; set; } }
public class Parent1 : IParent
{
public IChild[] Children { get; set; }
public Parent1(IChild[] children) { Children = children; }
}
public class Parent2 : IParent
{
public IChild[] Children { get; set; }
public Parent2(IChild[] children) { Children = children; }
}
public interface IChild{}
public class Child1 : IChild{}
public class Child2 : IChild{}
我使用ArrayResolver
为父母解决了多个孩子。
我需要的是,当我解决Parent1
时,我只获得Child1
实现(可能还有一些总是存在的)
但是当我解决Parent2
时,我想添加Child2
。
我的第一次尝试是:
[TestFixture]
public class BasicUnderstandingTests
{
[Test]
public void CanAddImplementationInOverride()
{
var container = new WindsorContainer();
container.Kernel.Resolver
.AddSubResolver(new ArrayResolver(container.Kernel));
container.Register(Component
.For<IParent>().ImplementedBy<Parent1>());
container.Register(Component
.For<IParent>().ImplementedBy<Parent2>().Named("Parent2")
.ServiceOverrides(ServiceOverride.ForKey<IChild>().Eq<Child2>()));
container.Register(Component
.For<IChild>().ImplementedBy<Child1>());
container.Register(Component
.For<IChild>().ImplementedBy<Child2>());
var p1 = container.Resolve<IParent>();
Assert.IsAssignableFrom<Parent1>(p1);
Assert.AreEqual(1, p1.Children.Length);
var p2 = container.Resolve<IParent>("Parent2");
Assert.IsAssignableFrom<Parent2>(p2);
Assert.AreEqual(2, p2.Children.Length);
}
}
但如果两个实现IChild
都被注册,则第一个断言失败,如果只注册了第一个实现,则第二个断言失败。
有没有一种优雅的方式可以做到这一点我错过了?
答案 0 :(得分:1)
好的,这是一个主要黑客,但这是一个有趣的小项目。我创建了一个自定义ISubDependencyResolver
来处理这种情况(种类)。试试这个:而不是ArrayResolver:
public class ParentChildResolver : ISubDependencyResolver
{
private readonly IKernel kernel;
public ParentChildResolver(IKernel kernel)
{
this.kernel = kernel;
}
public object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
{
var number = model.Name.Substring(model.Name.Length - 1, 1);
var childType = Type.GetType(String.Format("{0}.Child{1}", model.Service.Namespace, number));
var children = kernel.ResolveAll<IChild>().Where(c => childType.IsAssignableFrom(c.GetType())).ToArray();
return children;
}
public bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
{
return typeof (IChild[]).IsAssignableFrom(dependency.TargetType);
}
}
它有一些主要的假设,使它真的很hacky:
你也可以摆脱服务覆盖,因为它没有做任何事情。
由于内核将所有子节点视为IChild对象,因此我无法想到更简单的方法。您需要查看这些IChild对象是否由父类的特定类型实现 - 我将这些对象与数字后缀相匹配。
像我说的那样 - 主要的黑客。 :)