Identifying properties that override base properties or implement interfaces - c#

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" that T implements, (2) a base class "B" that T inherits from, or (3) the class T 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) where I is an interface that T implements
This is more complicated. I found that I can use an InterfaceMapping to find the corresponding implementation of the p in T. 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) where B is a class that T inherits from
I have not yet been able to figure out how to identify the property on T that overrides a virtual property p defined in Ts base class B.
So my questions are
In case 3 how do I find the PropertyInfo on T that overrides the property p on B?
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

Related

Get all static properties from a class

I know that there are many questions like this, but I couldn't find any answer to what I'm trying to do.
Considering the following abstract class:
public abstract class TestBase
{
public static ITest Test => Container.Resolve<ITest>();
public static ITest1 Test1 => Container.Resolve<ITest1>();
public static ITest2 Test2 => Container.Resolve<ITest2>();
public static ITest3 Test3 => Container.Resolve<ITest3>();
}
I'm trying to get all the properties that inherit from an interface IDummy like this:
var members = typeof(TestBase).GetMembers(BindingFlags.Static | BindingFlags.Public)
.Where(f => f.GetType().IsAssignableFrom(typeof(IDummy)) == true);
but the list is empty. Without adding the where clause ".Where(f => f.GetType().IsAssignableFrom(typeof(IDummy)) == true)" I get all the results including the getters for the properties.
Probably is something trivial, but as I'm not so familiar with reflection I can't figure out what I'm doing wrong.
What you get back from GetMembers is MemberInfo instances (or, for fields, FieldInfo instances). Hence, you cannot check these objects directly for being assignable from IDummy.
What you actually want to do is filter the MemberInfo objects for fields, then check the FieldType property of each of these objects:
var members = typeof(TestBase).GetMembers(BindingFlags.Static | BindingFlags.Public)
.OfType<FieldInfo>()
.Where(f => typeof(IDummy).IsAssignableFrom(f.FieldType));
Also, note that I turned around the subject and object of the IsAssignableFrom call, as also suggested in Patrick's comment.
As I just noticed, your example seems to show properties rather than fields. The general technique is the same, though; just use PropertyInfo and PropertyType rather than FieldInfo and FieldType, respectively.
Lastly, rather than filtering for PropertyInfo yourself, you could also use the one of the overloads of the GetProperties method directly.

Get protected property value of base class using reflection

I would like to know if it is possible to access the value of the ConfigurationId property which is located in the base class of the object and it's private. I have tried to do it with reflection with no luck.
To access ConfigurationId property i have used following code:
SubsetController controller = new SubsetController(new CConfigRepository(new FakeDataContextRepository()));
var myBaseClassProtectedProperty =
controller.GetType().BaseType
.GetProperty("CCITenderInfo", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(controller);
var myProtectedProperty =
CCITenderInfo.GetType()
.GetProperty("ConfigurationId", BindingFlags.Public | BindingFlags.Instance)
.GetValue(myBaseClassProtectedProperty);
Assuming the following parent and child class:
class BaseClass
{
private string privateField = "I'm Private";
}
class ChildClass : BaseClass
{
}
You can read privateField's value from a ChildClass instance using reflection like this:
ChildClass childInstance = new ChildClass();
object privateFieldValue = childInstance.GetType().BaseType
.GetField("privateField", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(childInstance);
Console.WriteLine(privateFieldValue); // I'm Private
To add to this answer - you should use the Instance and NonPublic binding flags for sure, but you should also ensure that you are actually referencing properties and not fields.
E.g. if you have
protected string Andrew;
You will not be able to get this via GetProperty, no matter what binding flags you use. Why - because it is a field, and not a property...
To fix this, just change it to
protected string Andrew {get;set;}
and then you can use the GetProperty method.
Yes, this is possible with reflection.
However, in order to look up nonpublic members, you'll need to use the reflection overload which take BindingFlags parameters. In order to look up private members, you'll also need to access via the typeof the base class, even when using BindingFlags.FlattenHierarchy. This also means you'll need to use the exact binding, however note that contradictory flags (such as using both NonPublic and Public) are valid and will return either at that point.
Be aware that the very need to look up nonpublic members could be considered code smell, and you should do so very carefully. Also be aware that nonpublic members are not guaranteed to have the same names across different versions.

Check if a "Type" override a dynamic type

We are giving some repetitive jobs to a consultant company, we just have a few constraints that could not be checked by compilation, like a requirement to override a specific property in all class implementing a specific interface.
The property of the interface, which should be overrided in all classes has the following signature:
dynamic Definition{get;}
I found this stackoverflow question: How to find out if property is inherited from a base class or declared in derived?
Which is closed to my case, but in my case, the property is defined is inherited class and overrided in this one:
public class ClassA:IMyInterface
{
public virtual dynamic Definition{get{ /*return SomethingSpecificToClassA;*/}}
}
public class ClassB:ClassA
{
public override dynamic Definition{get{ /*return SomethingSpecificToClassB;*/}}
}
//The end goal is to know if ClassB has correctly overriden the property
bool overriden = typeof(ClassB)GetProperties(...).Any(p=>p.Name=="Definition");
This is the solution: you ask ClassB its interface map, you look for the method you want in the interface map and then you look where the implementation method (classMethod) is declared.
var interfaceMethod = typeof(I).GetProperty("Definition").GetGetMethod();
var map = typeof(ClassB).GetInterfaceMap(typeof(I));
var ix = Array.IndexOf(map.InterfaceMethods, interfaceMethod);
var classMethod = map.TargetMethods[ix];
bool isDeclaredInClass = classMethod.DeclaringType == typeof(ClassB);
You can find for property declared only in your type of interests:
var prop = typeof (ClassB).GetProperty("Definition", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
Then you can then check if its getter is virtual:
prop.GetMethod.IsVirtual
which will be false if Definition hides (or uses new) in ClassB

GetFields of derived type

I am trying to reflect the fields in a derived type but it's returning the fields of the
base type.
public class basetype
{
string basevar;
}
public class derivedtype : basetype
{
string derivedvar;
}
In some function:
derivedtype derived = new derivedtype();
FieldInfo[] fields = derived.GetType().GetFields();
This will return basevar, but not derivedvar. I've tried all the different bindings and it doesn't seem to make a difference.
Also, I'm doing this in ASP.NET within App_Code where basevar is defined in App_Code and derivedvar is a user control defined in App_Controls where the types are not in scope.
As is, this will return nothing as the default binding is for public fields only.
As is also, derivedtype isn't derived from basetype
With:
FieldInfo[] fields = derived.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
It returns derivedvar. I've just checked in LINQPad.
If I change derivedtype to be derived from basetype, then I can get both fields with:
FieldInfo[] fields = derived.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Concat(derived.GetType().BaseType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)).ToArray();
Reflection is a bit odd.
If the members are public, all of them up the entire hierarchy are visible.
If the members are non-public, you have to specify BindingFlags.NonPublic and you will only get those members that are of the type used. Inherited members are not visible. If you want to see all the non-public members of a type you'll have to walk up the inheritence chain.

Get all base property declarations within a class hierarchy

Consider this interesting set of types:
class A { public virtual int MyProperty { get; set; } }
class B : A { public override int MyProperty { get; set; } }
class C : B { public new virtual int MyProperty { get; set; } }
class D : C { public override int MyProperty { get; set; } }
class E : D { public new int MyProperty { get; set; } }
I see three different properties here, with five implementations hiding or overriding each other.
I'm trying to get the set of property declarations for type E:
A.MyProperty
C.MyProperty
E.MyProperty
But my code below gives me the set of property implementations:
A.MyProperty
B.MyProperty
C.MyProperty
D.MyProperty
E.MyProperty
What do I need to do to get the property declarations?
Or is there any chance that B.MyProperty will ever return a value other than A.MyProperty for any instance of E?
If my approach is heading in the wrong direction: How do I get all property members of a type including any hidden ones, but not including those that will never have different values?
void GetProperties(Type type)
{
if (type.BaseType != null)
{
GetProperties(type.BaseType);
}
foreach (var item in type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public))
{
Console.WriteLine("{0}.{1}", type.Name, item.Name);
}
}
Desired outputs:
typeof(A) typeof(B) typeof(C) typeof(D) typeof(E)
------------ ------------ ------------ ------------ ------------
A.MyProperty A.MyProperty A.MyProperty A.MyProperty A.MyProperty
C.MyProperty C.MyProperty C.MyProperty
E.MyProperty
This may get you started down the path that you want:
static void GetProperties(Type type)
{
if (type.BaseType != null)
{
GetProperties(type.BaseType);
}
foreach (var item in type.GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public))
{
MethodInfo method = item.GetGetMethod();
MethodInfo baseMethod = method.GetBaseDefinition();
System.Diagnostics.Debug.WriteLine(string.Format("{0} {1}.{2} {3}.{4}", type.Name, method.DeclaringType.Name, method.Name, baseMethod.DeclaringType, baseMethod.Name));
if (baseMethod.DeclaringType == type)
{
Console.WriteLine("{0} {1}", type.Name, item.Name);
}
}
}
This code outputs the following:
A MyProperty
C MyProperty
E MyProperty
Note that this code depends on using the MethodInfo of the get method associated with the property. If you happen to have set-only properties, then you'll need to do some extra checks to handle that case.
but not including those that will never have different values?
It seems you are expecting the Reflection system to include rules for this very particular case. If it did, somebody else would complain that the B and D properties were missing.
But I think the answer is: D.MyProperty is listed from a recursive call. You know you already listed E.MyProperty so it might seem unnecessary but what if you called GetProperties(D)? Would you like it to be omitted?
Each of these is both a declaration and implementation (as none of them are abstract, so they all define method bodies). The keywords override and new are little more than hints to the runtime about which implementation to pick given the context of an instance. With reflection, you're bypassing normal inheritance tracing and invoking a specific implementation.
Given that, you can still figure out which of these will be the "root" call made from various points in the hierarchy. Recall that properties in .NET are pretty much syntactic sugar for a specific getter and setter method structure and a backing field, accessed as if the accessors were the field itself. Thus, a PropertyInfo exposes GetGetMethod() and GetSetMethod() which will return MethodInfo objects. You should only need one of the two as they'll both have the inheritance qualifiers given to the property, but make sure that your property has a get or a set at all levels of the hierarchy or this will blow up.
Now, MethodInfo exposes several properties regarding accessibility and inheritance. Of importance to you is the IsHideBySig property. If this returns true, then this method, as declared on the current type, is hiding an identical signature on its parent using the new keyword. So, in your code, you want to look at the members, and test two things; whether the type has a base type other than Object (or an abstract type you specify), and whether IsHideBySig on the getter or setter is true. If either of those is true, this is a "root" implementation for any type between the current type and the next most derived type with a similar "root".
So, your foreach would end up looking something like this:
foreach (var item in type.GetProperties(
BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)
.Where(pi=>pi.GetGetMethod().IsHideBySig || pi.ReflectedType.BaseType == typeof(Object))
{
Console.WriteLine("{0} {1}", type.Name, item.Name);
}
Now remember that these "roots" are not the ones that will be called, unless their children explicitly call them using the base identifier, and this can happen regardless of whether the current property hides or overrides its parent. The difference is in which implementation will be invoked by the runtime when an instance is cast as one of its ancestor types. In that case, the implementation chosen is that of the most derived type in the inheritance chain between cast and actual types, starting from the cast type, which does not hide its parent. If the most direct descendant of the cast type hides its parent, the cast type's implementation is used regardless of what that implementation does to its parent.
In your hierarchy, those would be B, D and E. If you declared a new E and invoked MyProperty, you'd get E's implementation. Then, if you passed it to a method that takes any A and accesses MyProperty, it would use B's implementation. If you declared an E and treated it as a C, it would use D's implementation. If you created a C and treated it as such, you'd get C's implementation (because a C is not a D), but if you treated it as an A you'd get B's implementation.

Categories