Castle Windsor接口的多种实现
Castle Windsor multiple implementations of interface
我有以下安装程序,但由于某些奇怪的原因,它无法正确解析。我有一个接口,其中有 2 个实现,但想根据 naming conventions
.
注入正确的实例
我希望在这种情况下,ICommand
的正确实例将根据它们的命名方式被注入。然而,出于某种奇怪的原因,两个控制器都选择了第一个实例,即 FooCommand
因为它首先在安装程序中定义。
不确定我做错了什么?也许,有其他方法可以做到这一点吗?
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());
就像@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));
}
}
}
}
棘手的一点是:
new ParameterModel(dependency.DependencyKey,
ReferenceExpressionUtil.BuildReference(dependency.DependencyKey))
它基本上告诉温莎依赖(构造函数参数),例如fooCommand
应该满足同名组件(fooCommand
)。
然后将您的贡献者添加到容器中
container.Kernel.ComponentModelBuilder.AddContributor(new ControllerCommandMatcher());
我有以下安装程序,但由于某些奇怪的原因,它无法正确解析。我有一个接口,其中有 2 个实现,但想根据 naming conventions
.
我希望在这种情况下,ICommand
的正确实例将根据它们的命名方式被注入。然而,出于某种奇怪的原因,两个控制器都选择了第一个实例,即 FooCommand
因为它首先在安装程序中定义。
不确定我做错了什么?也许,有其他方法可以做到这一点吗?
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());
就像@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));
}
}
}
}
棘手的一点是:
new ParameterModel(dependency.DependencyKey,
ReferenceExpressionUtil.BuildReference(dependency.DependencyKey))
它基本上告诉温莎依赖(构造函数参数),例如fooCommand
应该满足同名组件(fooCommand
)。
然后将您的贡献者添加到容器中
container.Kernel.ComponentModelBuilder.AddContributor(new ControllerCommandMatcher());