I am given:
A class "
T
" which implements properties that are decorated with Attributes that I am interested in.A
PropertyInfo
"p
" representing a property belonging to (1) an interface "I
" thatT
implements, (2) a base class "B
" thatT
inherits from, or (3) the classT
itself.
I need to get the Attributes defined on (or inherited by) the properties in T, even if p
's DeclaringType is an interface that T
implements or a class that T
inherits from. So I need a way to get from p
to the PropertyInfo
that actually exists on T
. Thus it seems that there are 3 cases:
p.DeclaringType == typeof(T)
This is the trivial case. I can iterate through
T
's properties until I find the match. Example:return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .FirstOrDefault(property => property == p)
p.DeclaringType == typeof(I)
whereI
is an interface thatT
implementsThis is more complicated. I found that I can use an InterfaceMapping to find the corresponding implementation of the
p
inT
. It seems kind of hackish, but here what works:if (p.DeclaringType.IsInterface && typeof(T).GetInterfaces().Contains(p.DeclaringType)) { InterfaceMapping map = typeof(T).GetInterfaceMap(p.DeclaringType); MethodInfo getMethod = p.GetGetMethod(); for (int i = 0; i < map.InterfaceMethods.Length; i++) { if (map.InterfaceMethods[i] == getMethod) { MethodInfo target = map.TargetMethods[i]; return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .FirstOrDefault(property => property.GetGetMethod() == target); } } }
p.DeclaringType == typeof(B)
whereB
is a class thatT
inherits fromI have not yet been able to figure out how to identify the property on 开发者_如何学Python
T
that overrides a virtual propertyp
defined inT
s base classB
.
So my questions are
- In case 3 how do I find the
PropertyInfo
onT
that overrides the propertyp
onB
? - Is there a better way to do all three? Perhaps a way to unify the three cases.
I think you're missing a case : it is possible that T
just inherits the property from B
, without overriding it (unless you know for sure this won't happen in your specific scenario).
Anyway, you just need to search the property by name, using typeof(T).GetProperty
, since there can't be 2 properties with the same name in a given class (unlike methods, which can have several overloads). However, you need to watch out for the case where T
hides the property inherited from B
, using the new
modifier. To handle that case, you can check the Attributes
of the property's getter method (obtained with GetGetMethod
) : if the NewSlot
flag is present, it hides the inherited getter.
I found a way to answer case 3. The key is MethodInfo.GetBaseDefinition
if (typeof(T).IsSubclassOf(p.DeclaringType))
{
MethodInfo baseDefinition = p.GetGetMethod().GetBaseDefinition();
return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.FirstOrDefault(property => property.GetGetMethod().GetBaseDefinition() == baseDefinition);
}
However this only works for properties that have been overridden on T
.
Edit:
By comparing the following, it doesn't matter if the properties have or haven't been overriden on T
:
property.GetGetMethod().GetBaseDefinition().MetadataToken == baseDefinition.MetadataToken
精彩评论