跨DLL双向调用抛出System.Reflection.TargetException问题咨询
解决跨DLL反射调用时的“对象不匹配目标类型”异常
这个问题我之前踩过好几次坑,核心原因基本都和跨程序集反射时的类型隔离有关——CLR对类型的识别是“类型全名+所属程序集”,哪怕是完全一样的类,只要来自不同的加载上下文,就会被当成完全不同的类型。咱们拆解下常见原因和解决办法:
最常见的问题:重复加载了同一个程序集
比如你加载DLL A的时候,第一次用Assembly.LoadFrom,第二次在B里又用Assembly.Load加载了一遍同名DLL,或者因为加载路径的问题,CLR加载了同一文件的副本,导致内存里存在两份完全独立的程序集实例。这时候A里的类和B里加载的A的类,在CLR眼里根本不是一回事,调用自然会报错。
解决办法:
- 统一程序集加载方式:比如全程用
Assembly.LoadFrom加载目标DLL,或者把DLL放到应用程序的基目录,用Assembly.Load("程序集的全名")来加载,避免重复加载。 - 快速验证:在调用前后分别打印目标类型的
Assembly.FullName,比如:
如果输出不一样,那肯定是重复加载了。// 在A里打印自己的类型程序集 Console.WriteLine(typeof(YourClassInA).Assembly.FullName); // 在B里打印获取到的A的类型程序集 Console.WriteLine(targetType.Assembly.FullName);
反射调用时的类型来源不匹配
比如你在B里为了调用A的方法,自己加载了A的程序集并获取了类型,但实际传入的实例是A那边创建的(这个实例的类型来自A自己的程序集)。这时候用B加载的类型去调用A实例的方法,CLR就会认为“对象类型和方法所属类型不匹配”。
解决办法:
- 不要在B里单独加载A的程序集获取类型,而是直接通过传入的实例来获取类型:
// 正确做法:从实例本身获取类型 Type targetType = instanceFromA.GetType(); MethodInfo method = targetType.GetMethod("YourMethod"); method.Invoke(instanceFromA, parameters); - 或者让A主动把自己的
Type对象传递给B,B用这个Type来获取方法再调用,确保类型来源一致。
参数类型不兼容的隐性问题
有时候你调用的方法需要传入A里的某个类作为参数,但你在B里创建了一个同名同结构的类实例传进去——哪怕代码完全一样,CLR也会因为它们来自不同程序集而判定类型不匹配,进而触发异常。
解决办法:
- 所有参数的实例都应该从同一个程序集加载的类型创建,最好是直接从A那边传递过来,而不是在B里重新加载类型创建实例。
- 如果必须在B里创建参数实例,确保用来创建实例的类型是从A的程序集(或者和A实例同来源的类型)获取的。
调试小技巧
- 捕获异常时,不要只看外层的
TargetInvocationException,一定要看内部的InnerException,这里才是真正的错误原因。 - 可以加一行代码快速验证类型匹配:
这行代码能直接帮你定位是不是程序集重复加载导致的类型隔离问题。if (!method.DeclaringType.Equals(instance.GetType())) { Console.WriteLine($"类型不匹配:方法所属类型 {method.DeclaringType.Assembly.FullName},实例类型 {instance.GetType().Assembly.FullName}"); }
内容的提问来源于stack exchange,提问作者randomgui
相关产品推荐
相关产品推荐

