65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2014 年 1 月 15 日

CPOL

2分钟阅读

viewsIcon

11019

如何在使用 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
	}
        }
    }

当然,你的条件逻辑会有所不同(希望如此);并且,为了使这有效,你需要创建多个(在本例中为两个)实现每个接口的类。

如果不同的用户应该获得不同的实现者,或者你想在调试/测试时使用某些类,而在“生产”代码中使用其他类,那么这种场景对你可能有用。

就写到这里吧!

© . All rights reserved.