C# Castle Windsor:强制解析程序使用指定的构造函数
以下是一个例子:C# Castle Windsor:强制解析程序使用指定的构造函数,c#,.net,dependency-injection,castle-windsor,ioc-container,C#,.net,Dependency Injection,Castle Windsor,Ioc Container,以下是一个例子: interface IComponentA {}; class ComponentA : IComponentA { }; interface IComponentB { }; class ComponentB : IComponentB { }; interface IComponentC { }; class ComponentC : IComponentC { public ComponentC(IComponentA a) {
interface IComponentA {};
class ComponentA : IComponentA { };
interface IComponentB { };
class ComponentB : IComponentB { };
interface IComponentC { };
class ComponentC : IComponentC
{
public ComponentC(IComponentA a)
{
Console.WriteLine("Constructor A");
}
public ComponentC(IComponentB b)
{
Console.WriteLine("Constructor B");
}
};
所有这些组件均在Castle Windsor容器中注册
但是类ComponentC
有2个重载构造函数。当激活组件C
时,可以使用其中任何一个
我需要使用ComponentC(IComponentB)
构造函数
目前,我正在使用FactoryMethod()方法来解决这个问题:
container
.Register(Component
.For<IComponentA>()
.ImplementedBy<ComponentA>())
.Register(Component
.For<IComponentB>()
.ImplementedBy<ComponentB>())
.Register(Component
.For<IComponentC>()
.UsingFactoryMethod(() => new ComponentC(
container.Resolve<IComponentB>())));
容器
.寄存器(组件)
.对于()
.ImplementedBy())
.寄存器(组件)
.对于()
.ImplementedBy())
.寄存器(组件)
.对于()
.使用FactoryMethod(()=>新组件C(
container.Resolve());
这是可行的,但温莎城堡可能提供了更好的方法
非常感谢您的帮助
谢谢。温莎不支持这种情况,因为它打破了它(和大多数容器)运行时基于的一个不成文假设:“所有构造函数都是平等的” 这意味着,无论选择哪个构造函数,组件的行为都不应该有功能上的差异。在所有条件相同的情况下,一个组件的依赖性越强,它的功能就越多,这就是为什么Windsor倾向于首先选择更贪婪的构造函数,但如果像您这样的情况,我想说的是,两种情况中的一种正在发生:
- 您的组件实际上可能是伪装成一个组件的两个组件。在这种情况下,您可能会想要拆分它
- 您的组件实际上使用它所拥有的两个依赖项进行操作,因此它应该有一个构造函数来接受这两个依赖项
public class Foo
{
public Foo(ISession session){/*code*/}
public Foo(ISessionFactory factory):this(factory.OpenSession()){}
}
虽然一开始这似乎是一个聪明的想法,但充其量它是多余的、令人困惑的和不必要的。如果您的案例与此类似,我将删除第二个构造函数 嗯,这很糟糕,但有一种方法(我过去不得不使用Linq2Sql DataContext对象来实现这一点)。您创建了一个decorator类并注册它 假设您有这个接口:
public interface IService
{
void DoSomething();
}
您的实现如下所示:
public class Service : IService
{
private readonly ILogger _logger;
public Service(ILogger logger)
: this(logger, SomeDefaultListOfThings())
{
}
// Let's say Windsor is calling this ctor for some reason (ArrayResolver?)
public Service(ILogger logger, IEnumerable<object> emptyArrayFromWindsor)
{
_logger = logger;
PutTheItemsSomewhere(emptyArrayFromWindsor);
}
public void DoSomething()
{
// Something that relies on the list of items...
}
}
然后您将注册该类:
container.Register(
Component.For<IService>()
.ImplementedBy<SpecificCtorServiceDecorator>());
container.Register(
用于()的组件
.ImplementedBy());
当然,最好不要在其他构造函数中使用这种奇怪的默认值(),但是如果您不能控制实际需要的类(比如我在Linq2Sql中,或者如果它是对API的一个突破性更改),那么这可能会帮您摆脱麻烦。如果它适合您的模型,您可以尝试使用类型化工厂设施。我相信它会自动选择与传递给工厂方法的参数相匹配的构造函数。这意味着您必须有一个工厂和该类型的实例才能传入,tho。如果您最终保留了现有代码,并且如果在同一安装程序中注册这两个代码,并且如果<代码>组件B 不存在依赖关系,请考虑跳过“代码> > ICOMPONTUNTB< <代码> />代码> ICOMPONTRON/<代码>的注册。一些注释(例如,
isubdependencysolver
)也可能有用。为什么使用哪个.ctor会有关系?@Krzysztof Koźmic例如构造函数ComponentC(IComponentA)
自行创建IComponentB
,而不使用容器中的IComponentB
<代码>组件C(IComponentB)自行创建IComponentA
,不使用容器中的IComponentA
。因此,ComponentC
在这些情况下的行为是不同的。我想说,你可能在你的班上有两个职责,也许你应该把它们分开?很好的解释。我同意这一点。谢谢。你的第一个要点把我带到了固体范式的单一责任原则。真是令人印象深刻的回答!你的回答让我大开眼界,解决了我队友观察到的一个神秘的温莎城堡行为。我们正在进行一个ASP.net MVC项目,该项目中的控制器具有重载构造函数,我很困惑,为什么DI容器总是使用最多的参数调用构造函数。
container.Register(
Component.For<IService>()
.ImplementedBy<SpecificCtorServiceDecorator>());