Inheritance and Reflection
In inheritance relationships, subclasses can inherit functionality, including methods, properties, fields and events from their superclasses, or base classes. A subclass will usually then add further members or override inherited members to modify or replace their functionality.
When you reflect over types that inherit functionality, details of members in superclasses can be included in the returned information. You can control which members are returned during reflection by adding two binding flags that we have not yet seen in this tutorial. This article will describe the use of these binding flags. The example code will concentrate on retrieving multiple properties. However, the binding flags can be used for other member types and when returning a single member from a type.
As we'll be using types form the System.Reflection namespace, add the following using directive:
For the samples we need some types to reflect over. We'll use the two classes shown below. Superclass is the base class that defines one static member and one instance member. These members are inherited by the type, "Subclass", which adds a second instance property.
public class Superclass
{
public static string SuperStaticProperty { get; set; }
public string SuperInstanceProperty { get; set; }
}
public class Subclass : Superclass
{
public string SubInstanceProperty { get; set; }
}
Instance Member Reflection in Inheritance Hierarchies
We'll start by looking at reflection of instance members. When you request all of the public members of a class using a reflection method that returns multiple members and uses no arguments, all appropriate instance members are returned. These include members declared directly in the class being examined and the members defined in superclasses throughout the hierarchy.
This is demonstrated by the code below. Here we are retrieving all of the properties from the Subclass type. As you can see from the results, the instance properties from both the subclass and the base class are returned.
Type type = typeof(Subclass);
PropertyInfo[] info = type.GetProperties();
foreach (var member in info)
{
Console.WriteLine(member.Name);
}
/* OUTPUT
SubInstanceProperty
SuperInstanceProperty
*/
In some cases you will wish to limit the members returned to only those directly declared within the reflected type. You can effectively hide base class instance members from reflection by applying the DeclaredOnly binding flag to your method calls. When using this constant, inherited members are not included in the results.
Try changing the line of code that performs the reflection to that shown in the below. Here we are applying the DeclaredOnly binding flag along with the Instance and Public flags. The results show that only the public instance member from Subclass is returned.
PropertyInfo[] info = type.GetProperties(
BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
/* OUTPUT
SubInstanceProperty
*/
Static Member Reflection in Inheritance Hierarchies
When you want to reflect static members the behaviour is different from that of instance members. As you can see from the first example above, when we requested information about all of the public properties of the subclass, the static property defined in the Superclass type was not returned. To obtain inherited static members we need to include the FlattenHierarchy binding flag.
PropertyInfo[] info = type.GetProperties(
BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
/* OUTPUT
SuperStaticProperty
*/
Private Base Type Members
When you are reflecting subtypes, only details of public, internal and protected members of their base classes are obtained. Private instance members from base classes are not returned, regardless of the binding flags used. To find information about these members you must obtain a System.Type instance for the base class and reflect the members of that type directly.
17 April 2012