You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自定义AssemblyLoadContext中使用MEF AssemblyCatalog

问题原因

AssemblyCatalog(来自传统MEF System.ComponentModel.Composition)默认依赖默认AssemblyLoadContext来扫描程序集中的导出部件(如标记[Export]的类型)。当你将插件程序集加载到自定义可回收ALC中时,默认ALC无法访问该程序集内的类型,因此扫描不到任何部件,导致Parts属性为空。而默认ALC加载时,程序集类型对扫描逻辑完全可见,所以功能正常。

解决方案

根据你使用的MEF版本,提供两种可行方案:

方案1:使用轻量级MEF(MEF2,System.Composition)

MEF2对自定义AssemblyLoadContext的支持更友好,无需额外处理即可扫描自定义ALC中的程序集部件。

  1. 安装NuGet包:

    Install-Package System.Composition
    Install-Package System.Composition.Hosting
    
  2. 修改代码实现:

    // 创建自定义可回收ALC
    var context = new AssemblyLoadContext(directoryInfo.FullName, true);
    // 加载插件程序集
    var assembly = context.LoadFromAssemblyPath(fileInfo.FullName);
    
    // 使用MEF2的容器配置加载程序集
    var containerConfig = new ContainerConfiguration()
        .WithAssembly(assembly);
    
    using (var container = containerConfig.CreateContainer())
    {
        // 获取所有导出的插件实例(替换为你的插件接口)
        var plugins = container.GetExports<IMyPlugin>();
        // 执行插件逻辑...
    }
    

方案2:自定义Catalog适配传统MEF

如果必须使用传统MEF(System.ComponentModel.Composition),可以手动实现Catalog,直接从自定义ALC加载的程序集中扫描导出类型:

using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;

public class AlcCompatibleAssemblyCatalog : ComposablePartCatalog
{
    private readonly List<ComposablePartDefinition> _parts = new();

    public AlcCompatibleAssemblyCatalog(Assembly assembly)
    {
        // 遍历程序集内所有类型,筛选带[Export]属性的类型
        foreach (var type in assembly.GetTypes())
        {
            if (type.GetCustomAttributes(typeof(ExportAttribute), inherit: true).Any())
            {
                // 将符合条件的类型转换为ComposablePartDefinition
                _parts.Add(new TypeCatalog(type).Parts.First());
            }
        }
    }

    public override IQueryable<ComposablePartDefinition> Parts => _parts.AsQueryable();
}

使用方式:

// 创建自定义ALC并加载程序集
var context = new AssemblyLoadContext(directoryInfo.FullName, true);
var assembly = context.LoadFromAssemblyPath(fileInfo.FullName);

// 使用自定义Catalog
var catalog = new AlcCompatibleAssemblyCatalog(assembly);
var container = new CompositionContainer(catalog);

// 获取导出部件
var plugins = container.GetExportedValues<IMyPlugin>();
注意事项
  • 确保插件程序集中的目标类型已正确标记[Export]属性(对应你使用的MEF版本)。
  • 自定义ALC需加载插件的所有依赖程序集,否则扫描类型时会抛出找不到依赖的异常。
  • 卸载ALC前,务必释放所有从容器获取的插件实例及容器本身,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Eleasar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:37:09