.NET 6中ReflectionOnlyLoad已弃用 有无替代方案可检测程序集自定义特性?
.NET 6 中
Assembly.ReflectionOnlyLoad 的替代方案 核心替代工具:MetadataLoadContext
.NET 6 官方推荐使用 System.Reflection.MetadataLoadContext 替代已弃用的 ReflectionOnlyLoad 系列API,它可以独立于主应用域加载程序集的元数据,不会将程序集实际加载到当前应用的执行上下文中,完全满足筛选程序集时避免加载不必要依赖的需求。
使用步骤
- 首先安装NuGet包
System.Reflection.MetadataLoadContext,版本匹配项目的.NET 6目标框架即可 - 构造
MetadataLoadContext实例时传入核心依赖解析逻辑,通常只需加载目标路径下的程序集,同时引入运行时核心程序集System.Runtime即可完成元数据读取 - 遍历目标路径下的所有dll文件,用
MetadataLoadContext.LoadFromAssemblyPath()加载元数据,该操作不会对主应用域产生任何影响 - 读取程序集的自定义特性,筛选出符合要求的程序集路径
- 筛选完成后释放
MetadataLoadContext,再用常规的Assembly.LoadFrom()加载筛选出的目标程序集即可
示例代码片段
using System.Reflection; using System.Reflection.MetadataLoadContext; // 收集目标路径所有程序集 + 运行时核心程序集路径,用于MetadataLoadContext的依赖解析 var appPath = @"你的应用程序路径"; var appAssemblyPaths = Directory.GetFiles(appPath, "*.dll", SearchOption.TopDirectoryOnly); var runtimeCorePath = Path.GetDirectoryName(typeof(object).Assembly.Location)!; var allResolverPaths = appAssemblyPaths.Concat(new[] { Path.Combine(runtimeCorePath, "System.Runtime.dll") }).ToArray(); using var mlc = new MetadataLoadContext(new PathAssemblyResolver(allResolverPaths)); var targetAssemblyPaths = new List<string>(); // 替换为你自定义特性的完整名称 var targetAttributeFullName = typeof(你要匹配的自定义特性).FullName; foreach (var dllPath in appAssemblyPaths) { try { var assembly = mlc.LoadFromAssemblyPath(dllPath); // 检查是否携带目标自定义特性 if (assembly.GetCustomAttributesData().Any(attr => attr.AttributeType.FullName == targetAttributeFullName)) { targetAssemblyPaths.Add(dllPath); } } catch (BadImageFormatException) { // 非托管dll或无效.NET程序集直接跳过 continue; } } // 筛选完成后,正常加载目标程序集到主应用域 foreach (var path in targetAssemblyPaths) { Assembly.LoadFrom(path); }
注意事项
MetadataLoadContext中读取的Type/Assembly实例和主应用域加载的实例不兼容,仅可用于元数据筛选,不能直接拿到主应用域使用- 用完
MetadataLoadContext要及时释放,避免占用额外内存 - 解析特性时建议用
GetCustomAttributesData而不是GetCustomAttributes,可以避免需要把特性对应的依赖也加载到MetadataLoadContext中
内容的提问来源于stack exchange,提问作者Mark Nisc
相关产品推荐
相关产品推荐

