加载外部程序集时如何忽略程序集差异获取带NUnit属性的方法?
解决跨程序集属性匹配问题
核心原因
CLR中,类型的唯一性由类型全名 + 所在程序集共同决定。你本地项目的TestAttribute和外部DLL引用的TestAttribute来自不同程序集,CLR会判定为不同类型,直接用typeof(TestAttribute)匹配自然失败。
可行解决方案
方案1:通过属性全名匹配
跳过类型直接比较,转而检查自定义属性的完整类型名称(命名空间+类名),不依赖程序集一致性:
private static IEnumerable<MethodInfo> GetTestMethods() { var alc = new TestAssemblyLoadContext("SomeDll.dll"); Assembly assembly = alc.LoadFromAssemblyPath("SomeDll.dll"); // 定义要匹配的属性全名 var targetAttributeNames = new HashSet<string> { "NUnit.Framework.TestAttribute", "NUnit.Framework.TestCaseAttribute" }; var testMethods = assembly.GetTypes() .SelectMany(t => t.GetMethods()) .Where(m => m.GetCustomAttributes(false) .Any(attr => targetAttributeNames.Contains(attr.GetType().FullName))); alc.Unload(); return testMethods; }
方案2:从外部程序集获取属性类型
直接从加载的外部Assembly中找到对应的属性类型,再用该类型匹配:
private static IEnumerable<MethodInfo> GetTestMethods() { var alc = new TestAssemblyLoadContext("SomeDll.dll"); Assembly assembly = alc.LoadFromAssemblyPath("SomeDll.dll"); // 从外部程序集中获取目标属性类型 Type testAttrType = assembly.GetType("NUnit.Framework.TestAttribute"); Type testCaseAttrType = assembly.GetType("NUnit.Framework.TestCaseAttribute"); var testMethods = assembly.GetTypes() .SelectMany(t => t.GetMethods()) .Where(m => m.GetCustomAttributes(testAttrType, false).Length > 0 || m.GetCustomAttributes(testCaseAttrType, false).Length > 0); alc.Unload(); return testMethods; }
方案3:共享NUnit程序集(推荐同版本场景)
如果本地项目和外部DLL使用同版本NUnit,可以让AssemblyLoadContext复用当前AppDomain里的NUnit程序集,避免加载重复版本:
自定义AssemblyLoadContext并重写Load方法:
public class SharedAssemblyLoadContext : AssemblyLoadContext { public SharedAssemblyLoadContext() : base(isCollectible: true) { } protected override Assembly Load(AssemblyName assemblyName) { // 优先加载当前AppDomain已有的程序集(比如NUnit) var existingAssembly = AppDomain.CurrentDomain.GetAssemblies() .FirstOrDefault(a => a.GetName().FullName == assemblyName.FullName); if (existingAssembly != null) { return existingAssembly; } // 其他程序集按默认逻辑加载 return LoadFromAssemblyName(assemblyName); } } // 使用修改后的LoadContext private static IEnumerable<MethodInfo> GetTestMethods() { var alc = new SharedAssemblyLoadContext(); Assembly assembly = alc.LoadFromAssemblyPath("SomeDll.dll"); var testMethods = assembly.GetTypes() .SelectMany(t => t.GetMethods()) .Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Length > 0 || m.GetCustomAttributes(typeof(TestCaseAttribute), false).Length > 0); alc.Unload(); return testMethods; }
注意事项
- 方案1、2适用于NUnit版本不同的场景,方案3仅支持版本完全一致的情况
- 方案3需确保外部DLL的NUnit版本与本地项目匹配,否则可能引发兼容性问题
内容的提问来源于stack exchange,提问作者user19824680
相关产品推荐
相关产品推荐

