问题
I do some type analysis in runtime using Reflection. If I have a MethodInfo instance, how can I figure out if this is a "real" method or is a getter/setter method of a property? And if it is a property, how can I find the its hosting PropertyInfo back?
回答1:
Ecma 335 specifies (but does not demand) that compilers use the get_/set_ prefixes (chapter 22.28). I don't know any language that breaks that recommendation. Making it easy:
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);
}
回答2:
Well, the method behind a getter and setter are "real" methods.
Re tracking back to a property - the pattern (return vs take 1 arg) will help narrow it - but you'll have to call GetGetMethod/GetSetMethod on each to find the property.
You could probably try the Name
(less get__/set__) - but that feels brittle. Here's the longer version (no use of 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();
}
}
回答3:
Look into MethodBase.IsSpecialName. Methods which shouldn't be plainly visible, such as property accessors, event subscription methods and operator overloads use this flag.
To my knowledge, there isn't a way to find the PropertyInfo
without iterating through the properties and comparing the methods.
回答4:
I'd really like to leave this as a comment, but I cant since my rep isnt high enough :(
Theres a bug in Marc Gravell's code: if its an indexer it will return null, even when a parent property exists. Its nice to have that quick-fail, but I think we can only do so when it has neither a return value or a parameter:
[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);
}
}
回答5:
The trick to play with is BindingFlags.DeclaredOnly and IsSpecialName
来源:https://stackoverflow.com/questions/520138/finding-the-hosting-propertyinfo-from-the-methodinfo-of-getter-setter