Castle Windsor:强制解析器使用指定的构造函数

Ale*_*iuk 7 .net c# 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)
    {
        Console.WriteLine("Constructor A"); 
    }

    public ComponentC(IComponentB b) 
    {
        Console.WriteLine("Constructor B");
    }
};
Run Code Online (Sandbox Code Playgroud)

所有这些组件都在Castle Windsor容器中注册.

但是类ComponentC有2个重载的构造函数.ComponentC激活时可以使用它们中的任何一个.

我需要使用ComponentC(IComponentB b)构造函数.

我暂时使用UsingFactoryMethod()方法来解决这个问题:

container
    .Register(Component
        .For<IComponentA>()
        .ImplementedBy<ComponentA>())
    .Register(Component
        .For<IComponentB>()
        .ImplementedBy<ComponentB>())
    .Register(Component
        .For<IComponentC>()
        .UsingFactoryMethod(() => new ComponentC(
            container.Resolve<IComponentB>())));
Run Code Online (Sandbox Code Playgroud)

它有效,但可能Castle Windsor提供了一些更好的方法吗?

任何帮助都非常感谢.

谢谢.

Krz*_*mic 6

Windsor不支持这种情况,因为它打破了(和大多数容器)基于以下操作的一个不成文的假设:"所有构造函数都是相同的".

这意味着,无论它选择哪种构造函数,组件的行为都不应存在功能差异.在所有条件相同的情况下,组件具有的依赖性越多,它就具有越多的功能,这就是为什么Windsor会首先选择贪婪的构造函数,但是如果像你的那样,我会说两件事情中的任何一件都发生了:

  • 你的组件实际上可能是伪装成一个组件的两个组件.在这种情况下,您可能希望将其拆分.
  • 你的组件实际上确实与它具有的两个依赖项一起运行,因此它应该有一个构造函数来获取它们.

我见过的另一个场景是这样的:

public class Foo
{
   public Foo(ISession session){/*code*/}
   public Foo(ISessionFactory factory):this(factory.OpenSession()){}
}
Run Code Online (Sandbox Code Playgroud)

虽然这看起来似乎是一个聪明的主意,但充其量是多余的,令人困惑和不必要的.如果你的情况看起来像这个,我只是删除第二个构造函数.

  • 你的第一个要点让我接受了SOLID范式的单一责任原则.确实非常令人印象深刻 你的回答结束了我的一天,并解决了我的队友正在观察的神秘的温莎城堡行为.我们正在开发一个ASP.net MVC项目,该项目具有带有重载构造函数的控制器,我很困惑,DI容器总是如何调用具有最多参数的构造函数. (2认同)