有人经常使用 Microsoft 的托管扩展性框架 (MEF) 吗?听起来有点像它试图满足所有人的需求——它是一个插件管理器!这是鸭子打字!我想知道是否有人有过这样的经历,无论是积极的还是消极的。

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

有帮助吗?

解决方案

我们的目标并不是让 MEF 成为一个通用的 IoC。考虑 MEF IoC 方面的最佳方法是实现细节。我们使用 IoC 作为一种模式,因为它是解决我们想要解决的问题的好方法。

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

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

其他提示

本文涉及托管可扩展性框架预览版 2。

因此,我浏览了 MEF 并写了一个快速的“Hello World”,如下所示。我得说它非常容易深入和理解。目录系统非常棒,使得 MEF 本身的扩展变得非常简单。将其指向插件程序集的目录并让它处理其余的事情很简单。MEF 的传统 ala Prism 确实表现出来了,但我认为如果没有表现出来就会很奇怪,因为这两个框架都是关于组合的。

我认为最令我惊讶的是 _container.Compose() 的“魔力”。如果您查看 HelloMEF 类,您会发现问候字段从未由任何代码初始化,这感觉很有趣。我想我更喜欢 IoC 容器的工作方式,在这种方式中,你明确地要求容器为你构建一个对象。我想知道某种“无”或“空”通用初始值设定项是否合适。IE。

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

这至少会用“某物”填充该对象,直到容器组合代码运行以用真正的“某物”填充它为止。我不知道 - 它有点像 Visual Basic 的 Empty 或 Nothing 关键字,我一直不喜欢这些关键字。如果其他人对此有一些想法,我想听听他们的意见。也许这是我需要克服的事情。它被标记为一个大的[导入]属性,所以它不像是一个完全神秘的东西。

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

我不太清楚鸭子打字功能是如何工作的。它看起来更像是对象创建时的元数据注入,而不是鸭子类型。看起来你只能添加一只额外的鸭子。但就像我说的,我还不太清楚这些功能是如何工作的。希望我以后能回来填写这个。

我认为对 DirectoryPartCatalog 加载的 DLL 进行卷影复制是个好主意。现在,一旦 MEF 掌握了 DLL,它们就会被锁定。这还允许您添加目录观察程序并捕获更新的插件。那会很甜蜜...

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

好吧——废话够多了。这是 MEF 和 C# 中的 Hello World。享受!

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

关于 Andy 提出的 MEF 加载扩展的安全问题(抱歉我还没有足够的分数:)),解决这个问题的地方是在目录中。MEF 目录是完全可插入的,因此您可以编写一个自定义目录来在加载之前验证程序集密钥等。如果您愿意,您甚至可以使用 CAS。我们正在考虑提供挂钩,让您无需编写目录即可执行此操作。但是,当前目录的来源是免费提供的。我怀疑至少有人(也许是我们团队中的人)会实现一个并将其放入 CodePlex 上的扩展/贡献项目中。

鸭子打字不会在 V1 中提供,尽管它在当前的下降中。在未来的版本中,我们将用可插拔适配器机制取代它,人们可以在其中挂钩鸭子打字机制。我们研究鸭子类型的原因是为了解决版本控制场景。使用 Duck Typing,您可以删除导出器和导入器之间的共享引用,从而允许合同的多个版本并存。

Andy,我相信 Glenn Block 在 MSDN MEF 论坛上的这个帖子中回答了许多人(自然的)问题:

CompositionContainer 与传统 IoC 容器的比较 .

在某种程度上,Artem 的上述答案相对于 MEF 背后的主要意图是正确的,即可扩展性而不是组合。如果您主要对组合感兴趣,请使用其他常见的 IoC 嫌疑人之一。另一方面,如果您主要关心可扩展性,那么目录、部件、元数据标记、鸭子类型和延迟加载的引入都会带来一些有趣的可能性。另外,克日什托夫·奇瓦利纳 (Krzysztof Cwalina) 也投篮 这里 解释 MEF 和 System.Addins 如何相互关联。

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

我想说,鉴于它将挂在 .NET 4.0 Framework 中的“System”命名空间中,您不会错得太离谱。看看 MEF 如何发展以及 Hamilton Verissimo(Castle)对 MEF 的方向有何影响将会很有趣。

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

这篇文章和评论中对此进行了更详细的讨论

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top