我在运行时使用Reflection进行一些类型分析.如果我有一个MethodInfo实例,我怎么能弄清楚这是一个"真正的"方法还是一个属性的getter/setter方法?如果它是一个属性,我怎样才能找到它的托管PropertyInfo?
嗯,getter和setter背后的方法是 "真正的"方法.
重新追溯到一个属性 - 模式(返回vs取1 arg)将有助于缩小它 - 但你必须在每个上调用GetGetMethod/GetSetMethod才能找到属性.
你可能会尝试Name
(少得到__/set__) - 但这感觉很脆弱.这是较长的版本(不使用Name
):
static PropertyInfo GetProperty(MethodInfo method) { bool takesArg = method.GetParameters().Length == 1; bool hasReturn = method.ReturnType != typeof(void); if (takesArg == hasReturn) return null; if (takesArg) { return method.DeclaringType.GetProperties() .Where(prop => prop.GetSetMethod() == method).FirstOrDefault(); } else { return method.DeclaringType.GetProperties() .Where(prop => prop.GetGetMethod() == method).FirstOrDefault(); } }
Ecma 335指定(但不要求)编译器使用get_/set_前缀(第22.28章).我不知道任何违反该建议的语言.轻松一点:
public static PropertyInfo GetPropFromMethod(Type t, MethodInfo method) { if (!method.IsSpecialName) return null; return t.GetProperty(method.Name.Substring(4), BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); }
看看MethodBase.IsSpecialName
.不应明显可见的方法(如属性访问器,事件订阅方法和操作员重载)使用此标志.
据我所知,没有办法找到PropertyInfo
没有迭代属性和比较方法.
我真的想留下这个作为评论,但我不能,因为我的代表不够高:(
这是Marc Gravell代码中的一个错误:如果它是一个索引器,它将返回null,即使存在父属性.很高兴快速失败,但我认为只有当它既没有返回值或参数时我们也可以这样做:
[Pure] public static PropertyInfo GetParentProperty(this MethodInfo method) { if (method == null) throw new ArgumentNullException("method"); var takesArg = method.GetParameters().Length == 1; var hasReturn = method.ReturnType != typeof(void); if (!(takesArg || hasReturn)) return null; if (takesArg && !hasReturn) { return method.DeclaringType.GetProperties().FirstOrDefault(prop => prop.GetSetMethod() == method); } else { return method.DeclaringType.GetProperties().FirstOrDefault(prop => prop.GetGetMethod() == method); } }