使用MEF进行DLL的延迟加载

5

我正在使用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个回答

6

首先,您正在尝试将对象导入到静态属性中。这是MEF不支持的:MEF组成对象,而不是。如果您想初始化静态属性,您必须手动执行如下操作:

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

现在来谈谈关于懒加载: DirectoryCatalog 会为目录中的每个程序集创建一个 AssemblyCatalog。MEF 中的 AssemblyCatalog 实现会在调用 AssemblyCatalog.Parts 时枚举程序集中的所有类型,而这将在您从容器中提取导出时发生。这意味着即使在 MEF 确定它实际需要某个部件之前,程序集也已经被加载了。
为了真正实现程序集的懒加载,有关哪些部件可用于这些程序集的信息需要被缓存到某个地方。MEF 目前并没有这样的内置缓存机制。但是,在包含在CodePlex上的MEF源代码示例中,有一个ComposablePartCatalogAssemblyCache实现。 Lazy<T> 的唯一作用就是推迟部件的构造函数被调用的时刻。这可以加快速度,但不会推迟程序集的加载。

1
MEF的一个很好的特性是(默认情况下)不需要初始化对象; MEF会匹配任何已声明的[Export],并将它们与您的导入匹配,并进行MEF初始化。如果您的依赖关系本身具有依赖关系,MEF将一直沿着链条继续,直到解析整个图形。
使用Lazy(而不是T)意味着实例化将延迟,直到访问该依赖项为止。如果您正在调试,并且没有看到该依赖项何时被初始化,您需要访问其Value属性以启动实例化。
MEF和大多数其他IoC容器之间存在一些重大区别(因为MEF专注于可扩展性/组合),但它类似于IoC容器在类型注册后,将在解析某些内容时实例化依赖项。
如果您想了解如何更改某些实例化行为的详细信息,请参阅此处的创建策略:http://mef.codeplex.com/wikipage?title=Parts%20Lifetime

0
这是一个非常老的问题,但对于任何寻找解决方案的人,我最近实现了一个LazyAssemblyCatalog,它可以在仍然使插件元数据可用的情况下延迟加载插件程序集,而无需加载这些程序集。它的概念与@Wim在他的答案中提到的CachedAssemblyCatalog非常相似。我希望这对任何人都有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接