ASP.NET MVC反射中如何判断MethodInfo的CallingConvention为Standard|HasThis?
问题:ASP.NET MVC反射场景下判断类是否不存在标准非静态公共Getter
我正在开发一个ASP.NET MVC项目,处理反射相关功能时,需要判断某个类是否不存在标准的非静态公共getter,编写了如下代码:
public static bool NotHavePublicGetter(Type deger, string propertyName) { try { if (deger == null) throw new ArgumentNullException("Type"); if (string.IsNullOrEmpty(propertyName)) throw new ArgumentNullException(typeof(string).ToString()); PropertyInfo[] propertyInfoDizisi = deger.GetProperties(BindingFlags.Public | BindingFlags.Instance); if (propertyInfoDizisi == null || !propertyInfoDizisi.Any()) throw new InvalidOperationException("propertyInfoDizisi == null || !propertyInfoDizisi.Any()"); MethodInfo getterMethodInfo = null; StringBuilder getDotNetName = new StringBuilder(); getDotNetName.Append("get_"); getDotNetName.Append(propertyName); foreach (PropertyInfo propertyInfo in propertyInfoDizisi) { if (propertyInfo == null) continue; getterMethodInfo = propertyInfo.GetGetMethod(false); if (getterMethodInfo == null) continue; // 此处需要检查getterMethodInfo的CallingConvention属性 if (getDotNetName.ToString().Equals(getterMethodInfo.Name)) return false; } return true; } catch (ArgumentNullException hata) { //TODO productionda kalkacak. //YAP2 testte aktive edilecek. throw hata; } catch (InvalidOperationException hata) { //TODO productionda kalkacak. //YAP2 testte aktive edilecek. throw hata; } catch (Exception hata) { //TODO productionda kalkacak. //YAP2 testte aktive edilecek. throw hata; } //TODO productionda aktive gelecek. //YAP2 testte deaktive edilecek. //return true; }
调试时发现getterMethodInfo.CallingConvention的属性值为Standard | HasThis,但用getterMethodInfo.CallingConvention == CallingConventions.Standard || getterMethodInfo.CallingConvention == CallingConventions.HasThis判断时返回false,请问如何正确检查该属性是否为Standard | HasThis?
解决方案
这是因为CallingConventions是带有FlagsAttribute的枚举类型,多个枚举值通过按位或组合,不能直接用相等运算符==判断单个值。正确的检查方式有两种:
1. 使用按位与运算判断组合值
通过按位与运算,验证目标枚举值是否同时包含Standard和HasThis:
// 定义需要检查的组合约定 var requiredConventions = CallingConventions.Standard | CallingConventions.HasThis; // 按位与运算验证是否包含全部约定 if ((getterMethodInfo.CallingConvention & requiredConventions) == requiredConventions) { if (getDotNetName.ToString().Equals(getterMethodInfo.Name)) return false; }
2. 使用HasFlag方法(.NET Framework 4.0+支持)
HasFlag方法可以直接判断枚举是否包含指定的单个或组合值:
if (getterMethodInfo.CallingConvention.HasFlag(CallingConventions.Standard) && getterMethodInfo.CallingConvention.HasFlag(CallingConventions.HasThis)) { if (getDotNetName.ToString().Equals(getterMethodInfo.Name)) return false; }
代码优化建议
你当前通过拼接get_前缀匹配getter方法名的方式可以简化,直接通过PropertyInfo.Name匹配目标属性名即可,无需操作方法名:
foreach (PropertyInfo propertyInfo in propertyInfoDizisi) { if (propertyInfo == null) continue; // 直接匹配属性名,避免字符串拼接 if (propertyInfo.Name != propertyName) continue; var getter = propertyInfo.GetGetMethod(false); if (getter == null) continue; // 检查调用约定 var requiredConventions = CallingConventions.Standard | CallingConventions.HasThis; if ((getter.CallingConvention & requiredConventions) == requiredConventions) { // 存在符合要求的公共getter,返回false return false; } }
这样代码更直观,也减少了不必要的字符串操作开销。
内容的提问来源于stack exchange,提问作者tahasozgen
相关产品推荐
相关产品推荐

