将MemberInfo转换为Func<T1,T2,...>及MethodInfo遇阻求助
解决MemberInfo转MethodInfo失败的问题(结合.NET 4.7 + CodeDOM场景)
我来帮你排查这个转换失败的问题,结合你提到的.NET 4.7和CodeDOM动态编译的场景,咱们一步步拆解:
核心问题:RtFieldInfo本身就不是MethodInfo
你提到的RtFieldInfo是CLR内部的字段信息实现类,它属于FieldInfo的子类,根本不是方法成员,所以强行转MethodInfo肯定会失败。这说明你当前拿到的MemberInfo实例是字段,而非你想要的方法。
排查方向1:确认你获取的是方法成员
首先要检查你获取MemberInfo的代码逻辑,是不是不小心把字段、属性等其他成员混进来了:
- 如果你用的是
Type.GetMember()方法,记得指定精确的绑定标志,比如要获取静态公共方法的话,应该用:
(按需调整var members = targetType.GetMembers(BindingFlags.Static | BindingFlags.Public);Instance/Static、Public/NonPublic标志) - 更稳妥的方式是直接用
Type.GetMethods(),它只会返回方法成员,避免混入其他类型的成员:MethodInfo[] methods = targetType.GetMethods(BindingFlags.Static | BindingFlags.Public);
排查方向2:静态类/静态成员的影响
静态类或静态成员本身不会导致转换失败——静态方法对应的MemberInfo就是MethodInfo,静态字段对应的是FieldInfo,二者类型边界清晰。问题大概率出在你筛选成员的逻辑上,而非静态特性本身。
排查方向3:CodeDOM动态编译的潜在问题
CodeDOM编译的程序集可能会生成一些编译器辅助成员(比如自动属性的幕后字段),但核心的方法/字段类型还是符合CLR规范的。你可以做以下检查:
- 确认动态编译的程序集已经正确加载到当前AppDomain中,没有跨AppDomain操作的情况(不同AppDomain的类型无法直接转换)。
- 输出
MemberInfo的详细信息来验证:
通过foreach (var member in targetType.GetMembers()) { Console.WriteLine($"成员名称:{member.Name},类型:{member.GetType().FullName},成员类型:{member.MemberType}"); }MemberType属性可以直接判断是方法(MemberTypes.Method)还是字段(MemberTypes.Field)。
修复建议:安全转换的正确姿势
在转换前先判断类型,避免强制转换抛出异常:
foreach (var member in targetType.GetMembers()) { // 用模式匹配安全转换 if (member is MethodInfo methodInfo) { // 处理你的方法逻辑 Console.WriteLine($"找到方法:{methodInfo.Name}"); } else { // 跳过非方法成员,或者记录日志排查 Console.WriteLine($"跳过非方法成员:{member.Name}(类型:{member.MemberType})"); } }
如果是参考Marc Gravell的特定方案,建议再核对他的代码上下文——他的方案可能默认输入的MemberInfo都是方法成员,所以你需要确保自己的成员筛选逻辑和他的场景一致。
内容的提问来源于stack exchange,提问作者Ian Ray
相关产品推荐
相关产品推荐

