使用MEF延迟加载DLL

时间:2010-12-06 22:23:49

标签: c# .net mef

我正在用MEF做我的第一个项目,我很难理解如何使用延迟加载。我的代码是 -

public static class MefLoader
{
     private static CompositionContainer Container;

    [ImportMany(typeof(IControlModule), AllowRecomposition = true)]
    private static IEnumerable<Lazy<IControlModule, IImportComponentCapabilites>> 
               DllList { get; set; }

    static MefLoader()
    {
        var catalog = new AggregateCatalog();
        catalog.Catalogs.Add(new DirectoryCatalog("."));
        Container = new CompositionContainer(catalog);

    }

我理解大多数如何使用MEF,除了我没有看到如何初始化DllList对象。我想使用延迟加载,因为在最终系统中,我们有很多选项,任何时候都只会使用大约10%。

3 个答案:

答案 0 :(得分:6)

首先,您尝试将对象导入静态属性。 MEF不支持此功能:MEF组成对象,而不是。如果要初始化静态属性,则必须手动执行此操作:

DllList = container.GetExports<IControlModule, IImportComponentCapabilites>();

现在关于延迟加载:DirectoryCatalog为目录中的每个程序集创建一个AssemblyCatalog。 MEF中的AssemblyCatalog实现将在调用AssemblyCatalog.Parts时立即枚举程序集中的所有类型,这将在您从容器中提取导出时发生。这意味着即使在MEF确定它包含实际需要的部件之前,也会加载该组件。

为了真正延迟加载程序集,需要在某处缓存有关哪些部件在这些程序集中可用的信息。 MEF目前没有开箱即用的内置缓存机制。但是,MEF source code at codeplex中包含的示例中有ComposablePartCatalogAssemblyCache个实现。

Lazy<T>唯一能做的就是推迟调用部件的构造函数的那一刻。这可以加快速度,但不会推迟加载程序集。

答案 1 :(得分:1)

关于MEF的好处是(默认情况下) 不初始化对象; MEF将匹配任何与您的导入匹配的声明[导出],然后 MEF 为您提供。如果您的依赖项本身具有依赖项,则MEF将继续沿着链继续,直到您的整个图解析为止。

使用Lazy(而不是T)只意味着实例化将被延迟,直到您访问该依赖项。如果您正在调试,并且您没有看到何时初始化该依赖项,则需要访问Value属性以启动实例化。

MEF与大多数其他IoC容器之间存在一些重大差异(因为MEF只关注可扩展性/组合),但它类似于IoC容器在注册类型后将如何实例化依赖关系解决问题。

如果您对如何更改某些实例化行为感到好奇,请在此处详细介绍创建策略:http://mef.codeplex.com/wikipage?title=Parts%20Lifetime

答案 2 :(得分:0)

这是一个非常古老的问题,但对于寻找解决方案的任何人来说,我最近实现了一个LazyAssemblyCatalog,它允许延迟加载插件程序集,同时仍然可以使插件元数据可用,而无需加载这些组件。它的概念与@Wim在他的回答中提到的int main() { Point<float> mp{4.535, 395.3}; Point<int> ip = mp; print(mp); print(ip); return 0; } 非常相似。我希望这对任何人都有所帮助。