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

跨多个.NET程序集查找接口实现类时IsAssignableFrom返回false的问题

.NET6跨程序集反射中IsAssignableFrom返回false的原因及解决方法

问题场景

在.NET6跨多个程序集的反射场景中:

  • AssemblyA引用AssemblyB
  • AssemblyC引用AssemblyB,且AssemblyC中的TestLoading类实现了AssemblyB的ILoading接口
  • 调用typeof(ILoading).IsAssignableFrom(assembly.GetType("TestLoading"))返回false,但GetType().GetInterfaces()能正确获取到ILoading接口名称,且已确认所有必要程序集已加载

代码示例

Assembly A

public class SomeFunnyClass 
{
   public static void Main(string[] args)
   {
      Assembly.LoadFrom("AssemblyB.dll");
      Assembly assemblyC = Assembly.LoadFrom("AssemblyC.dll");
      SomeTests(assemblyC);
   }

   public void SomeTests(Assembly assembly) 
   {
      var test = assembly.GetType("TestLoading").GetInterfaces(); // 返回ILoading
      var test2 = typeof(ILoading).IsAssignableFrom(assembly.GetType("TestLoading")); // 返回false
   }
}

Assembly B

public interface ILoading 
{
   void OnLoad();
}

Assembly C

public class TestLoading : ILoading 
{
    public void OnLoad(){
       // 逻辑实现
    }
}

原因分析

核心问题是程序集重复加载导致的CLR类型标识不匹配:

  • AssemblyA本身引用了AssemblyB,应用启动时CLR会自动将AssemblyB加载到应用域中。
  • 手动调用Assembly.LoadFrom("AssemblyB.dll")会再次加载同一个物理文件的AssemblyB,此时CLR会将这两个加载的AssemblyB视为不同的程序集实例(即使文件内容完全一致,加载方式或路径差异会触发这个行为)。
  • 此时:
    • AssemblyA中typeof(ILoading)对应的是CLR自动加载的AssemblyB里的接口类型
    • AssemblyC的TestLoading类实现的是它自身引用的AssemblyB里的接口类型(该实例与AssemblyA手动加载的AssemblyB实例不同)
  • CLR判断类型相等的依据是类型的全名+所属程序集实例,两个不同AssemblyB实例中的ILoading会被视为完全不同的类型,因此IsAssignableFrom返回false。而GetInterfaces()仅返回类型名称字符串,所以看起来结果正确,但底层类型实例不匹配。

解决方法

1. 移除不必要的手动加载代码

AssemblyA已经引用了AssemblyB,CLR会自动负责加载该程序集,无需手动调用Assembly.LoadFrom。移除后,AssemblyC加载时会复用已存在的AssemblyB实例,类型标识即可匹配。

修改后的Assembly A代码:

public class SomeFunnyClass 
{
   public static void Main(string[] args)
   {
      // 移除Assembly.LoadFrom("AssemblyB.dll");
      Assembly assemblyC = Assembly.LoadFrom("AssemblyC.dll");
      SomeTests(assemblyC);
   }

   public void SomeTests(Assembly assembly) 
   {
      var testType = assembly.GetType("TestLoading");
      var test = testType.GetInterfaces(); 
      var test2 = typeof(ILoading).IsAssignableFrom(testType); // 现在返回true
   }
}

2. 统一程序集加载方式(若必须手动加载)

如果业务场景要求手动加载程序集,优先使用Assembly.Load(按程序集名称加载)而非Assembly.LoadFrom(按文件路径加载)。Assembly.Load会先检查应用域中是否已加载同名程序集,若存在则直接复用,避免重复加载导致的类型不匹配问题。

示例替换:

// 替换Assembly.LoadFrom("AssemblyB.dll")为:
Assembly.Load("AssemblyB"); // 确保AssemblyB的名称正确,且在应用搜索路径中

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 17:55:25