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

能否修改MethodInfo的DeclaringType?调用匿名方法遇实例类型错误

解决Controller调用跨类MethodInfo的实例类型不匹配问题

这个问题的核心是匿名方法的归属类型与Controller实例不兼容:你在Descriptor里创建的匿名Func<string>,会被编译器偷偷编译成Descriptor类的私有嵌套匿名类型中的方法,它的DeclaringType是那个嵌套类型,而Controller尝试用自身实例去调用这个属于Descriptor相关类型的方法,自然会触发实例类型验证失败的ArgumentException。

因为你无法修改Controller类,这里有两个可行的解决思路:

方案1:使用静态方法替代匿名方法

静态方法不依赖任何实例,调用时不会触发实例类型匹配检查,是最直接的解决方案:

// 在Descriptor类中定义静态方法
public static string GetFoo()
{
    return "foo";
}

// 获取对应的MethodInfo
var mx = typeof(Descriptor).GetMethod(nameof(GetFoo), BindingFlags.Public | BindingFlags.Static);

把这个mx传给Controller的构造函数,调用时就不会再出现实例类型不匹配的问题了。

方案2:用DynamicMethod生成无归属类型的方法

如果不想在Descriptor中显式定义静态方法,可以用System.Reflection.Emit.DynamicMethod创建一个不关联到任何具体类的方法,这样Expression验证时不会检查实例类型:

using System.Reflection.Emit;

// 在Descriptor中创建DynamicMethod
var dynamicMethod = new DynamicMethod(
    name: "DynamicGetFoo",
    returnType: typeof(string),
    parameterTypes: Type.EmptyTypes,
    module: typeof(Descriptor).Module);

// 编写IL代码返回"foo"
ILGenerator il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldstr, "foo");
il.Emit(OpCodes.Ret);

// 获取MethodInfo
var mx = dynamicMethod.GetMethodInfo();

DynamicMethod生成的方法不属于任何类,因此Controller调用时不会触发实例类型验证逻辑,完美绕过报错。

为什么原来的匿名方法不行?

编译器会把匿名方法包装成包含它的类(这里是Descriptor)的私有嵌套类中的实例方法,当Controller尝试用自身实例调用这个方法时,System.Linq.Expressions.Expression.ValidateCallInstanceType会检查实例类型是否是方法DeclaringType的子类或实现类,显然Controller和那个匿名嵌套类型完全无关,所以直接抛出异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:56:59