指定MetadataToken时Module.ResolveMethod()返回错误方法问题求助
这种情况我之前踩过坑,太懂那种“明明令牌没错,结果解析出完全不相关方法”的崩溃感了!结合我当时的排查经验,给你几个方向试试:
1. 确认你用对了模块
MetadataToken的作用域是模块级的,不是整个程序集。如果你的程序集包含多个模块,你在错误的模块上调用ResolveMethod(),就会拿到该模块中对应令牌值的方法——刚好和你目标方法的令牌撞号了,就出现了Dispose()令牌解析出OnBackColorChanged()的情况。
排查步骤:
- 先确认目标方法
Dispose()所属的模块:disposeMethod.Module - 确保你调用
ResolveMethod()的对象就是这个模块,而不是程序集里的其他模块。
2. 验证MetadataToken的准确性
有时候你以为拿到的是目标方法的令牌,其实可能搞错了来源:
- 比如你是不是从其他MethodInfo(比如父类的方法)那里拿到的令牌?或者调试时误拿了其他变量的令牌?
- 建议直接打印令牌的十六进制值对比:
MethodInfo targetMethod = typeof(YourClass).GetMethod("Dispose", Type.EmptyTypes); Console.WriteLine($"目标方法令牌:0x{targetMethod.MetadataToken:X}"); // 再打印你传入ResolveMethod的令牌值,看是否完全一致 - 也可以用dnSpy/ILSpy打开DLL,查看
MethodDef表,找到Dispose()对应的令牌,确认和你代码里用的是不是同一个。
3. 警惕泛型类型/方法的重载干扰
如果目标方法属于泛型类型,或者你调用了ResolveMethod()的泛型重载(带genericTypeArguments参数的那个),传入的泛型参数不匹配也可能导致解析错误。
正确的做法是:如果目标方法不在泛型上下文里,直接调用无泛型参数的ResolveMethod(int metadataToken)重载;如果是泛型方法,要确保传入正确的泛型类型参数数组。
4. 排查程序集是否被篡改/混淆
有些混淆工具(比如某些商业混淆器)在重命名方法时,可能会导致元数据令牌的映射出现异常;或者程序集被动态修改过(比如注入了代码),导致元数据表发生变化。
这种情况下,建议用dnSpy打开原始DLL和你正在解析的DLL,对比两者的MethodDef表,看令牌对应的方法是否一致。
正确示例代码
给你一个靠谱的参考代码,确保每一步都准确:
// 1. 获取目标方法的MethodInfo Type targetType = typeof(YourDisposableClass); MethodInfo disposeMethod = targetType.GetMethod("Dispose", Type.EmptyTypes); if (disposeMethod == null) { Console.WriteLine("找不到Dispose()方法"); return; } // 2. 确认令牌和所属模块 int disposeToken = disposeMethod.MetadataToken; Module targetModule = disposeMethod.Module; Console.WriteLine($"Dispose() 令牌:0x{disposeToken:X},所属模块:{targetModule.Name}"); // 3. 在正确的模块上解析 MethodInfo resolvedMethod = targetModule.ResolveMethod(disposeToken); Console.WriteLine($"解析得到的方法:{resolvedMethod.DeclaringType.Name}.{resolvedMethod.Name}");
如果试了这些还是解决不了,建议检查一下DLL的元数据完整性,或者看看是不是.NET版本的兼容性问题(比如用.NET Framework的API解析.NET Core的DLL可能有异常)。
内容的提问来源于stack exchange,提问作者Meme Machine

