序列化配置以实现依赖注入/控制反转

3
最近我一直在研究依赖注入和控制反转的实践,以改进我们应用框架的架构,但是我似乎找不到一个好的答案。很可能是我的术语混淆了,或者我对这个概念还很幼稚,所以希望能提供任何链接或澄清。
许多 DI 和 IoC 容器的示例并没有说明当你有一个“插件”库时,容器将如何连接这些插件,或者如何“序列化”给定的配置。(从我读过的有关 MEF 的内容来看,如果您的对象只需要 1 个 [Import],那么为同一类型声明多个 [Export] 将无效)。也许这是一种不同的模式,或者我被当前的思维方式蒙住了眼。
以下是一个示例参考代码:
public abstract class Engine {
}

public class FastEngine : Engine {
}

public class MediumEngine : Engine {
}

public class SlowEngine : Engine {
}

public class Car
{
    public Car(Engine e)
    {
        engine = e;
    }

    private Engine engine;
}

本文讨论了“细粒度上下文”概念,其中两个同一对象实例需要不同的“引擎”类实现: IoC.Resolve vs Constructor Injection 是否有一个很好的框架可以帮助您配置或序列化配置以实现这样的目标,而不是硬编码或手动编写代码来完成?
public class Application
{
    public void Go()
    {
        Car c1 = new Car(new FastEngine());
        Car c2 = new Car(new SlowEngine());
    }
}

示例 XML:

<XML>
    <Cars>
        <Car name="c1" engine="FastEngine" />
        <Car name="c2" engine="SlowEngine" />
    </Cars>
</XML>

感谢那些提供答案的人。 虽然其他答案给出了特定框架的示例,但被接受的答案指出许多 DI 框架都可以通过 XML 配置(如 Unity、Spring 等)来实现。根据平台和个人喜好选择使用哪种框架是由你决定的。 - Joshua Starner
3个回答

1

我不清楚mef,但Spring使用与您描述几乎完全相同的方法(通过XML文件或配置部分进行注入配置)实现了您所描述的功能:

<objects>
  <object name="FastCar" type="MyApp.Car">
    <constructor-arg>
       <ref object="FastEngine">
    </constructor-arg>
  </object>
  <object name="SlowCar" type="MyApp.Car">
    <constructor-arg>
       <ref object="SlowEngine">
    </constructor-arg>     
  </object>
  <object name="FastEngine" type="MyApp.FastEngine"/>
  <object name="SlowEngine" type="MyApp.SlowEngine"/>
</objects>

很酷,我看到了Spring的提及,但我没有继续阅读。我会去查一下的。谢谢! - Joshua Starner

0

使用MEF(你提到的),你可以使用[ImportMany]导入一组Engine实例。然后,您将能够为每个引擎创建一辆汽车,并返回它,无需XML。

public class Application
{
    [ImportMany]
    public IEnumerable<Engine> Engines { get; set; }

    public void Go()
    {
        // I'm assuming this object was composed already...

        var cars = this.Engines.Select(e => new Car(e));

        foreach(var car in cars)
        {
            // Do something with each car
        }
    }
}

这样做的好处是,您可以随时添加新的“引擎”,而无需更改代码。所有的连接都在运行时动态处理,无需配置。


谢谢Reed。我在MEF中找到了[ImportMany]属性,它似乎非常适合动态加载事物集合。我认为我要解决的问题是允许某人明确指定每辆汽车使用哪个对象。我可以看到使用这种方法如何在运行时添加新的Engine对象到列表中,但我需要一些方式来序列化“Car 1使用Fast Engine”的事实,因此当我创建Car 1并给它一个Fast Engine时。 - Joshua Starner

0

大多数 DI 容器都支持XML 配置 - 实际上,它们中的大多数最初就是这样,并且 XML 配置是唯一的选项。现在,XML 配置是几个选项之一

然而,在其当前版本中,MEF 不使用 XML 配置。它也不是 DI 容器。


谢谢提供链接。现在我对MEF有了更多的了解,我不认为未知运行时发现是我要寻找的。这似乎是XML配置和代码配置之间的开放性辩论。最终,我想构建一个工具包,可以被非程序员使用,以“钩子”方式连接一组丰富的程序员构建的库。听起来XML配置更适合这里。 - Joshua Starner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接