Reputation: 1247
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?
Upvotes: 26
Views: 5692
Reputation: 35318
For present day .NET, I believe the following is equivalent to Marc's answer but more concise and maybe a slight bit more efficient. I may have missed something.
public static PropertyInfo? GetPropertyInfo(this MethodInfo getSetMethodInfo)
=> getSetMethodInfo.DeclaringType?.GetProperties()
.FirstOrDefault(prop => prop.GetSetMethod() == getSetMethodInfo
|| prop.GetGetMethod() == getSetMethodInfo);
Upvotes: 0
Reputation: 26528
The trick to play with is BindingFlags.DeclaredOnly and IsSpecialName
Upvotes: -2
Reputation: 3239
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);
}
}
Upvotes: 5
Reputation: 942187
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);
}
Upvotes: 7
Reputation: 1063864
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();
}
}
Upvotes: 21
Reputation: 42162
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.
Upvotes: 5