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

加载外部程序集时如何忽略程序集差异获取带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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 16:25:21