[英]Castle Windsor multiple implementations of interface
I have the following installer but for some odd reason it is not resolving correctly.我有以下安装程序,但由于某些奇怪的原因,它无法正确解析。 I have an interface where there are 2 implementations of it but want to inject the correct instance based on
naming conventions
.我有一个接口,其中有 2 个实现,但想根据
naming conventions
注入正确的实例。
I am expecting in this instance that the correct instance of ICommand
will be injected based on how they are named.我期望在这种情况下,将根据它们的命名方式注入正确的
ICommand
实例。 However, for some odd reason both controllers are picking the very first instance, ie FooCommand
due to it being defined first in the installer.然而,出于某种奇怪的原因,两个控制器都选择了第一个实例,即
FooCommand
因为它是在安装程序中首先定义的。
Not sure what I have done wrong?不确定我做错了什么? Perhaps, is there an alternative way of doing this?
也许,有没有其他方法可以做到这一点?
public interface ICommand { }
public class FooCommand : ICommand { }
public class BarCommand : ICommand { }
public class SomeController : ApiController
{
public SomeController(ICommand fooCommand) { }
}
public class HelloController : ApiController
{
public HelloController(ICommand barCommand) { }
}
container.Register(
Component.For<ICommand>()
.Named("fooCommand")
.ImplementedBy<FooCommand>()
.LifestyleSingleton(),
Component.For<ICommand>()
.Named("barCommand")
.ImplementedBy<BarCommand>()
.LifestyleSingleton());
Like @steven said, it's generally not a good idea and if not managed properly may lead to discoverability issues down the line, but assuming you know what you're doing you can build a IContributeComponentModelConstruction
that will match constructor parameters of type ICommand
on your controllers with Windsor components having the same name.就像@steven 所说的那样,这通常不是一个好主意,如果管理不当可能会导致可发现性问题,但假设您知道自己在做什么,您可以构建一个
IContributeComponentModelConstruction
来匹配控制器上ICommand
类型的构造函数参数具有相同名称的 Windsor 组件。
public class ControllerCommandMatcher : IContributeComponentModelConstruction
{
public void ProcessModel(IKernel kernel, ComponentModel model)
{
// or whatever other condition to bail out quickly
if (model.Implementation.Name.EndsWith("Controller") == false) return;
foreach (var constructor in model.Constructors)
{
foreach (var dependency in constructor.Dependencies)
{
if (dependency.TargetItemType != typeof (ICommand)) continue;
dependency.Parameter = new ParameterModel(dependency.DependencyKey,
ReferenceExpressionUtil.BuildReference(dependency.DependencyKey));
}
}
}
}
The tricky bit is this:棘手的一点是:
new ParameterModel(dependency.DependencyKey,
ReferenceExpressionUtil.BuildReference(dependency.DependencyKey))
It basically tells Windsor that the dependency (the constructor parameter), for example fooCommand
should be satisfied with a component of the same name ( fooCommand
).它基本上告诉 Windsor 依赖项(构造函数参数),例如
fooCommand
应该满足同名组件( fooCommand
)。
Then add your contributor to the container然后将您的贡献者添加到容器中
container.Kernel.ComponentModelBuilder.AddContributor(new ControllerCommandMatcher());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.