【问题标题】:What is different between and purpose of MEF and Unity?MEF 和 Unity 的区别和目的是什么?
【发布时间】:2011-08-22 09:59:54
【问题描述】:

我刚开始学习 DI(我正在研究 WPF/Silverlight,但我有计划转向 ASP.NET)。在我从互联网上阅读了一些 DI 文章之后,有两个我感兴趣的框架,MEF 和 Unity。我想知道他们之间的现实世界有什么不同,哪一个比较好。

【问题讨论】:

标签: .net dependency-injection unity-container mef


【解决方案1】:

主要区别在于,通过统一,您将显式注册要在组合中使用的每个类:

var container = new UnityContainer();
container.RegisterType<IFoo,Foo>();
container.RegisterType<IBar,Bar>();
...
var program = container.Resolve<Program>();
program.Run();

另一方面,在 MEF 中,您使用属性标记类而不是在其他地方注册它们:

[Export(typeof(IFoo))]
public Foo
{
   ...
}

乍一看,这似乎是一个很小的语法差异,但实际上比这更重要。 MEF 旨在允许动态发现零件。例如,使用DirectoryCatalog,您可以设计您的应用程序,以便通过简单地将新的 DLL 拖放到应用程序文件夹中来扩展它。

在此示例中,MEF 将在给定目录中查找并实例化所有具有 [Export(typeof(IPlugin))] 属性的类,并将这些实例传递给 Program 构造函数:

[Export]
public class Program
{
    private readonly IEnumerable<IPlugin> plugins;

    [ImportingConstructor]
    public Program(
       [ImportMany(typeof(IPlugin))] IEnumerable<IPlugin> plugins)
    {
        this.plugins = plugins;
    }

    public void Run()
    {
        // ...
    }
}

入口点:

public static void Main()
{
    using (var catalog = new DirectoryCatalog(".","*"))
    using (var container = new CompositionContainer(catalog))
    {
        var program = container.GetExportedValue<Program>();
        program.Run();
    }
}

为了适应这种动态组合场景,MEF 有一个“稳定组合”的概念,这意味着当它在某个地方遇到缺失的依赖项时,它会简单地将部分标记为不可用,并且无论如何都会继续组合。

Stable composition can be quite useful,但它也使它成为very difficult to debug a failed composition。因此,如果您不需要动态发现部件和“稳定组合”,我会使用常规 DI 容器而不是 MEF。与 MEF 不同,常规 DI 容器会在缺少依赖项时为您提供清晰的错误消息。

还可以通过使用与 MEF 集成的 DI 容器(如 Autofac)来获得两全其美的效果。使用 Autofac 编写核心应用程序,使用 MEF 编写需要动态扩展的部分。

【讨论】:

  • 我希望事情就这么简单。不幸的是它不是。 MEF 让我非常头疼。它会引发大量“ImportCardinalityMismatchException”错误,这与 MEF 在调试功能方面的设计非常糟糕有关。我在错误代码中没有找到无法组装导出的参考。我即将彻底放弃与 MEF 合作的任何尝试。
  • @Freddy:尚不清楚您在评论我答案的哪一部分。我从字面上写道,“调试失败的组合非常困难”,并链接到我的博客文章。我在哪里说过这很容易?
  • 对不起,如果我误解了,您发布了 Main 方法并说“只需删除 DLL”和“MEF 将找到所有具有 Export 属性的类”,不幸的是,这几乎是简单明了的。我一直在为此拔毛。公平点重新调试。我更关心的是,MEF 的使用并不像人们在查看您的代码示例时想象的那么简单。也许我通过你的回答得到了错误的印象。
  • 这应该有助于调试 MEF: 1. 将 Visual Studio 调试器配置为在抛出异常时中断。 2. 配置您的 CompositionContainer 对象以禁用拒绝。 msdn.microsoft.com/en-us/library/ff603380%28v=vs.110%29.aspx
  • 需要指出的是,MEF 和 Unity 之间的差异是因为库的用途不同。 Unity 是一个 IoC 容器,旨在用于 DI。 MEF 不是 IoC 容器,即使您可以将其作为一个容器运行,但效果很差。 MEF 适用于Extensibility
【解决方案2】:

进行 DI 有很多选择。首先,您应该意识到 DI 不是关于工具,而是关于模式和原则。无需工具即可很好地使用 DI。如果你这样做,我们称之为Poor Man's DI

不过,话虽如此,there are lots of DI Containers available for .NET。 Unity 只是其中之一。

MEF 看起来很像 DI 容器,但目前解决了一个不同的问题 - 可扩展性问题。它使用基于属性的发现机制,而不是组件的外部配置(所有 DI 容器都使用)。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-08
  • 2019-07-12
  • 1970-01-01
  • 2020-03-19
  • 2012-09-03
  • 1970-01-01
  • 2011-01-05
相关资源
最近更新 更多