使用 Castle Windsor 实现接口的具体实现类的替换





5.00/5 (1投票)
如何在使用 Castle Windsor 的 IoC/DI 项目中替换接口映射
如果你不替换映射,IoC/DI 就失去了意义
这篇文章是对 此处 文章的一个补充。
控制反转的全部意义在于,你可以将接口的不同具体实现传递给一个控制器,该控制器期望一个实现特定接口的类,但并不指定或关心它接收的具体类是什么。
为了指定使用哪个实现类,你可能会编写如下代码
public class RepositoriesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<iduckbilledplatypusrepository>().ImplementedBy
<duckbilledplatypusrepository>().LifestylePerWebRequest(),
Component.For<isiberiantigerrepository>().ImplementedBy
<siberiantigerrepository>().LifestylePerWebRequest(),
Component.For<ibottlenoseddolphinrepository>().ImplementedBy
<bottlenoseddolphinrepository>().LifestylePerWebRequest(),
Component.For<ipterodactylrepository>().ImplementedBy
<pterodactylrepository>().LifestylePerWebRequest(),
Component.For<ibutterflyrepository>().ImplementedBy
<butterflyrepository>().LifestylePerWebRequest());
}
}
但是等等——“等等,伙计!”你可能会说。这不是很冗长吗?确实,还有其他方法——实际上有三种——你可以映射你的接口(也就是说,作为控制器构造函数中的参数类型的接口):你可以使用 XML 文件(优点是后期绑定),你可以使用自动布线或自动注册,允许编译器使用反射并注册你告诉它查找的所有接口,或者你可以像上面那样在代码中进行映射。第一种方法(XML)如今在很大程度上被认为已经过时,因为它与花生脆糖有些相似;中间一种(自动布线)绝对是酷炫度最高的(或者最酷的……算了);但我更喜欢后一种方法,如上所示,因为它易于阅读。而且,因为它易于阅读,所以易于维护(尽管有时会有些繁琐)并添加可理解的逻辑。
关于将你的具体类映射到你的接口的三种方法,这里有一个(恕我直言/YMMV)图表,展示了它们的优点/缺点
可理解性 | PIA 因子* | 花哨程度 | |
XML | 10 | 8 | 2 |
代码 | 10 | 5 | 4 |
自动布线 | 2 | 2 | 10 |
注意: PIA == “麻烦事”
别再来科学图表了!
所以,让我们回到正题。关于使用“代码”方法:例如(没有双关语),如果你想根据某个条件用另一组实现者替换一组实现者,很容易添加这种逻辑
const int HAPPINESS = 42;
int Money;
int Love;
. . .
public class RepositoriesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
if (Love == HAPPINESS)
{
container.Register(
Component.For>imammalrepository>().ImplementedBy>
duckbilledplatypusrepository>().LifestylePerWebRequest(),
Component.For>ifishrepository>().ImplementedBy>
bottlenoseddolphinrepository>().LifestylePerWebRequest(),
Component.For>ibirdrepository>().ImplementedBy>
pterodactylrepository>().LifestylePerWebRequest(),
Component.For>ireptilerepository>().ImplementedBy>
hornedtoadrepository>().LifestylePerWebRequest());
Component.For>iinsectrepository>().ImplementedBy>
beetlerepository>().LifestylePerWebRequest());
}
else if (Money == HAPPINESS)
{
container.Register(
Component.For>imammalrepository>().ImplementedBy>
siberiantigerrepository>().LifestylePerWebRequest(),
Component.For>ifishrepository>().ImplementedBy>
catfishrepository>().LifestylePerWebRequest(),
Component.For>ibirdrepository>().ImplementedBy>
africangreyparrotrepository>().LifestylePerWebRequest(),
Component.For>ireptilerepository>().ImplementedBy>
bullfrogrepository>().LifestylePerWebRequest());
Component.For>iinsectrepository>().ImplementedBy>
prayingmantisrepository>().LifestylePerWebRequest());
}
else
{
... // deal with it
}
}
}
当然,你的条件逻辑会有所不同(希望如此);并且,为了使这有效,你需要创建多个(在本例中为两个)实现每个接口的类。
如果不同的用户应该获得不同的实现者,或者你想在调试/测试时使用某些类,而在“生产”代码中使用其他类,那么这种场景对你可能有用。
就写到这里吧!