关于mef:.NET的哪种托管扩展框架?

关于mef:.NET的哪种托管扩展框架?

Whither Managed Extensibility Framework for .NET?

有没有人与微软的可管理扩展框架(MEF)合作过? Kinda听起来像是要尝试所有人的万物-它是外接程序管理器! 是鸭子打字! 我想知道是否有人对此有正面或负面的经验。

我们目前正计划在下一个大型项目中使用通用IoC实现ala MvcContrib。 我们应该把MEF混在一起吗?


我们不希望MEF成为通用IoC。考虑MEF的IoC方面的最佳方法是实现细节。我们将IoC用作模式,因为它是解决我们要解决的问题的好方法。

MEF专注于可扩展性。当您想到MEF时,将其视为推动我们平台发展的一项投资。我们未来的产品和平台将利用MEF作为增加可扩展性的标准机制。第三方产品和框架也将能够利用这种相同的机制。 MEF的普通"用户"将编写MEF将使用的组件,而不会在其应用程序中直接使用MEF。

想象一下,当您将来想要扩展我们的平台时,将dll放入bin文件夹中就可以了。启用了MEF的应用程序会随着新的扩展程序亮起。这就是MEF的愿景。


这篇文章引用了Managed Extensibility Framework Preview 2。

因此,我经历了MEF并撰写了一个快速的" Hello World",如下所示。我要说的是,完全容易理解和理解。目录系统很棒,可以很轻松地扩展MEF本身。将其指向加载项程序集的目录并让其处理其余部分很简单。 MEF的传统ala Prism确实可以证明这一点,但如果没有这样,我认为这很奇怪,因为这两个框架都是关于组合的。

我认为最困扰我的是_container.Compose()的"魔力"。如果查看HelloMEF类,您将看到greetings字段从未被任何代码初始化,这简直太可笑了。我想我更喜欢IoC容器的工作方式,即您明确要求容器为您构建对象。我不知道某种" Nothing"或" Empty"通用初始值设定项是否正确。即

1
private IGreetings greetings = CompositionServices.Empty<IGreetings>();

至少要用"东西"填充对象,直到容器组成代码运行时才用真实的"东西"填充对象。我不知道-它有点Visual Basic的Empty或Nothing关键字,我一直不喜欢它。如果有人对此有任何想法,我想听听他们的看法。也许这只是我需要克服的问题。它标有一个很大的[Import]胖属性,因此并不像是一个完整的谜一样。

控制对象的生命周期并不明显,但是默认情况下,一切都是单例的,除非您向导出的类添加[CompositionOptions]属性。让我们指定Factory或Singleton。很高兴看到Pooled在某个时候被添加到该列表中。

我不清楚鸭子的打字功能如何工作。看起来更像是在对象创建时进行元数据注入,而不是鸭子输入。而且看起来您只能添加另外一只鸭子。但是就像我说的那样,我还不清楚这些功能如何工作。希望我可以稍后再填写。

我认为对影子复制由DirectoryPartCatalog加载的DLL是一个好主意。现在,一旦MEF持有DLL,它们就会被锁定。这也将允许您添加目录观察器并捕获更新的插件。那真是太好了...

最后,我担心插件DLL的信任程度以及MEF在部分信任环境中的行为方式或行为方式。我怀疑使用MEF的应用程序将需要完全信任。将加载项加载到自己的AppDomain中可能也是明智的。我知道它有点System.AddIn,但是它可以使用户插件和系统插件之间非常清晰地分开。

好的-足够的起泡。这是MEF和C#中的Hello World。请享用!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
using System;
using System.ComponentModel.Composition;
using System.Reflection;

namespace HelloMEF
{
    public interface IGreetings
    {
        void Hello();
    }

    [Export(typeof(IGreetings))]
    public class Greetings : IGreetings
    {
        public void Hello()
        {
            Console.WriteLine("Hello world!");
        }
    }

    class HelloMEF : IDisposable
    {
        private readonly CompositionContainer _container;

        [Import(typeof(IGreetings))]
        private IGreetings greetings = null;

        public HelloMEF()
        {
            var catalog = new AggregateCatalog();
            catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
            _container = new CompositionContainer(catalog);
            var batch = new CompositionBatch();
            batch.AddPart(this);
            container.Compose(batch);

        }

        public void Run()
        {
            greetings.Hello();
        }

        public void Dispose()
        {
            _container.Dispose();
        }

        static void Main()
        {
            using (var helloMef = new HelloMEF())
                helloMef.Run();
        }
    }
}


鸭子类型不会在V1中提供,尽管它在当前版本中。在将来的版本中,我们将用可插入的适配器机制代替它,在该机制下,用户可以使用鸭子类型的机制。我们之所以选择鸭子类型,是为了解决版本问题。使用Duck Typing,您可以删除出口商和进口商之间的共享引用,从而允许合同的多个版本同时存在。


关于安迪关于MEF加载的扩展的安全性问题(很抱歉,我还没有足够的要点:)),解决此问题的地方在目录中。 MEF目录是完全可插入的,因此您可以在加载之前编写一个自定义目录来验证程序集密钥等。如果需要,您甚至可以使用CAS。我们正在寻找可能提供的挂钩,以使您无需编写目录即可执行此操作。但是,当前目录的来源是免费提供的。我怀疑最低限度是有人(也许在我们的团队中)将实现一个并将其扔到CodePlex的扩展/贡献项目中。


Ayende在这里也有很好的文章:http://ayende.com/Blog/archive/2008/09/25/the-managed-extensibility-framework.aspx


安迪,我相信Glenn Block在MSDN MEF论坛的这个主题中回答了许多类似这样的人(自然)问题:

CompositionContainer与传统IoC容器的比较。

在某种程度上,相对于MEF背后的主要意图(即可扩展性而不是组合性),上述Artem的答案是正确的。如果您主要对合成感兴趣,请使用其他常见的IoC嫌疑人之一。另一方面,如果您主要关注可扩展性,那么目录,零件,元数据标记,鸭子类型和延迟加载的介绍都会带来一些有趣的可能性。同样,Krzysztof Cwalina在这里解释了MEF和System.Addins如何相互关联。


我要说的是,由于它将与.NET 4.0 Framework中的"系统"名称空间挂在一起,所以您不会做错太多。看看MEF如何演变以及汉密尔顿·韦里斯西莫(城堡)对MEF的方向产生什么影响将是很有趣的。

如果它像鸭子一样嘎嘎叫,它可能只是当前IoC容器群的一部分...


这不是控制容器的注入。它是插件支持框架。


这篇文章和评论中对此有更详细的讨论

http://mikehadlow.blogspot.com/2008/09/managed-extensibility-framework-why.html


推荐阅读