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

.NET 6迁移时Assembly.ReflectionOnlyLoad相关弃用方法的替代方案

.NET 6 下 Assembly.ReflectionOnlyLoad 系列方法的替代方案

.NET Core/.NET 5+ 已彻底移除仅反射加载(Reflection Only Load)上下文的底层实现,Assembly.ReflectionOnlyLoad()、Assembly.ReflectionOnlyLoadFrom() 两个API在.NET 6及以上版本标记为弃用且调用会抛出异常,针对你扫描程序集级别特性筛选待处理程序集的场景,有两种官方推荐的替代实现。

方案1:使用 MetadataLoadContext(推荐,完全匹配原仅反射加载场景)

MetadataLoadContext 是专门为只读元数据扫描设计的组件,不会将程序集加载到当前运行时执行上下文,不会触发程序集内任何代码(静态构造函数、模块初始化器等)的执行,安全性和性能都更优,是原仅反射加载API的官方直替方案。
使用前需要先引入NuGet包 System.Reflection.MetadataLoadContext,适配后的代码如下:

// 构造元数据解析器,需要同时传入待扫描程序集路径、当前运行时核心程序集路径用于依赖解析
var runtimeDllPaths = Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll");
var resolver = new PathAssemblyResolver(assemblyFilenames.Concat(runtimeDllPaths));

// using包裹MetadataLoadContext,用完自动释放,不会锁定程序集文件、也不会残留元数据内存占用
using var metadataLoadCtx = new MetadataLoadContext(resolver);

foreach (var assemblyFile in assemblyFilenames)
{
    // 仅加载程序集元数据,无执行副作用
    var metaAssembly = metadataLoadCtx.LoadFromAssemblyPath(Path.GetFullPath(assemblyFile));
    if (FoundOurCustomAttr(metaAssembly))
    {
        // 筛选通过的程序集再加载到运行时执行上下文做业务处理
        var targetAssembly = Assembly.LoadFrom(assemblyFile);
        ProcessAssembly(targetAssembly);
    }
}

注意:MetadataLoadContext 中读取到的Type、Attribute对象均为元数据层面的快照对象,和运行时加载的类型不共享,所以FoundOurCustomAttr方法判断特性时请通过特性类型全名称匹配,不要做类型强转,否则会抛出类型不匹配异常。

方案2:使用可收集的 AssemblyLoadContext 做隔离加载

如果所有待扫描程序集都是内部可信来源,不想额外引入NuGet依赖,可以用可收集的自定义AssemblyLoadContext做隔离加载,扫描完成后直接卸载上下文即可,不会长期占用内存或锁定文件,适配代码如下:

foreach (var assemblyFile in assemblyFilenames)
{
    // 创建可收集的独立加载上下文,扫描完可完全卸载
    using var scanAlc = new AssemblyLoadContext("AssemblyScanCtx", isCollectible: true);
    try
    {
        var scanAssembly = scanAlc.LoadFromAssemblyPath(Path.GetFullPath(assemblyFile));
        if (FoundOurCustomAttr(scanAssembly))
        {
            // 筛选通过的程序集加载到默认上下文执行业务
            var targetAssembly = Assembly.LoadFrom(assemblyFile);
            ProcessAssembly(targetAssembly);
        }
    }
    finally
    {
        // 卸载扫描上下文,释放所有加载的非目标程序集
        scanAlc.Unload();
    }
}

方案选择建议

  • 待扫描程序集来源不完全可信、或待扫描程序集数量大时,优先选MetadataLoadContext,无执行副作用、内存占用更低,是官方首推方案。
  • 待扫描程序集均为内部可信、依赖关系简单时,可以选可收集AssemblyLoadContext方案,代码改动量最小,不需要额外依赖。

原代码中挂载的AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve事件在.NET 5+中没有对应仅反射上下文的实现,使用上述两种方案时,分别通过PathAssemblyResolver、自定义AssemblyLoadContext的Resolving事件处理依赖解析即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 03:48:22