我刚刚开始学习DI(我正在研究WPF / Silverlight,但我有计划转向ASP.NET)。在我从互联网上阅读了一些DI文章之后,有两个我感兴趣的框架,MEF和Unity。我想知道它们之间的真实世界有什么不同,哪一个是好的。
答案 0 :(得分:63)
主要区别在于,您将明确注册要在合成中使用的每个类:
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来处理需要动态扩展的部分。
答案 1 :(得分:19)
进行DI有很多选择。首先,您应该意识到DI不是关于工具,而是关于模式和原则。你可以在没有工具的情况下使用DI。如果你这样做,我们称之为穷人的DI 。
但是,那说there are lots of DI Containers available for .NET。 Unity只是其中之一。
MEF看起来很像DI容器,但目前解决了一个不同的问题 - 可扩展性问题。它不使用组件的外部配置(所有DI容器都使用),而是使用基于属性的发现机制。