以下是示例:
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个重载的构造函数。当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>())));
它有效,但Castle Windsor可能提供了一些更好的方法吗?
非常感谢任何帮助。
感谢。
答案 0 :(得分:6)
Windsor不支持这种情况,因为它打破了(和大多数容器)基于以下操作的一个不成文的假设:“所有构造函数都是相同的。”
这意味着,无论选择哪种构造函数,组件的行为都不应存在功能差异。在所有条件相同的情况下,组件拥有的依赖关系越多,它就越有能力,这就是为什么Windsor会首先选择贪婪的构造函数,但是如果像你的那样,我会说两件事情都发生了:
我见过的另一种情况是:
public class Foo
{
public Foo(ISession session){/*code*/}
public Foo(ISessionFactory factory):this(factory.OpenSession()){}
}
虽然这看起来似乎是一个聪明的主意,但充其量只是多余,混乱和不必要的。如果你的情况看起来像这个,我只是删除第二个构造函数。
答案 1 :(得分:1)
我们假设你有这个界面:
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...
}
}
但正如这个例子所暗示的那样,由于某些原因,温莎打电话给错误的ctor而你却无法说服它(正如Krzysztof指出的那样)。然后你可以创建如下的装饰器类,其中只有一个构造函数,从而消除了歧义:
public class SpecificCtorServiceDecorator : IService
{
private readonly IService _decorated;
public SpecificCtorServiceDecorator(ILogger logger)
{
_decorated = new Service(logger);
}
public void DoSomething()
{
_decorated.DoSomething();
}
}
然后您注册该课程:
container.Register(
Component.For<IService>()
.ImplementedBy<SpecificCtorServiceDecorator>());
当然最好不要让这个奇怪的默认值在其他构造函数中发生(search for "Poor-man's Dependency Injection"),但是在你不能控制类的情况下实际上想要(就像我在Linq2Sql中,或者如果它是对API的重大改变)那么这可能会让你摆脱困境。