【问题标题】:Serializing Configurations for a Dependency Injection / Inversion of Control依赖注入/控制反转的序列化配置
【发布时间】:2011-03-01 09:19:51
【问题描述】:

我最近一直在研究依赖注入和控制反转实践,以努力改进我们的应用程序框架的架构,但我似乎找不到这个问题的好答案。很可能我的术语混淆了,混淆了,或者我现在对这个概念很天真,所以任何链接或澄清将不胜感激。

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;
}

这篇文章讨论了“细粒度上下文”,其中同一对象的 2 个实例需要“引擎”类的不同实现: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 等)实现这一点。您可以根据平台和偏好确定使用哪一个。

标签: dependency-injection ioc-container mef


【解决方案1】:

使用 MEF(您提到过),您可以使用 [ImportMany] 导入引擎实例的集合。然后,您可以为每个引擎创建一辆汽车,然后返回它,而无需 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
        }
    }
}

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

【讨论】:

  • 谢谢里德。我确实在 MEF 中找到了 [ImportMany] 属性,这对于动态加载事物的集合来说似乎很棒。我认为我要解决的问题是允许某人明确说明每辆汽车使用哪个对象。我可以使用这种方法看到如何在运行时将新的引擎对象添加到列表中,但是我需要某种方式来序列化“汽车 1 使用快速引擎”这一事实,所以当我创建汽车 1 时,给它一个快速引擎.
【解决方案2】:

我不了解 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,但我没有继续阅读。我会检查一下。谢谢!
【解决方案3】:

大多数 DI 容器都支持 XML 配置 - 事实上,它们中的大多数都是以这种方式开始的,而 XML 配置是 only 选项。如今,XML configuration is one option among several.

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

【讨论】:

  • 感谢您的链接。现在我已经阅读了有关 MEF 的更多内容,我认为未知的运行时发现不是我正在寻找的。这看起来像是 XML 配置和代码配置之间的公开辩论。最终,我想构建一个工具包,非程序员可以使用它来“将事物连接在一起”,因为它有一组丰富的程序员构建的库。听起来 XML 配置更适合这里。
猜你喜欢
  • 2012-02-05
  • 2011-03-14
  • 1970-01-01
  • 2010-10-31
  • 1970-01-01
  • 1970-01-01
  • 2015-07-30
  • 1970-01-01
相关资源
最近更新 更多