Part of why I write some of these articles are to remind myself on how to do things. If one doesn’t do them every day they get lost with the rest of life’s memories. One of the topics I run into every so often is the need to enumerate an object and extract or set values of its properties. In this example I will create a generic function which will take in a class object and write out all of the public properties, the set those public properties.

Example

Here is the class we will reflect and notice it contains public and private properties.

The following code demonstrates how to enumerate over an object, list its properties and their values. It is divided into three static methods.
  1. The first method TestIT is the actual test method which can be called to show the operations for it creates a TestClass object to be reflected. This is used only for debug / show purposes.
  2. The second static OutputProperties shows the differences in how reflection of a class can change the values and a gotcha which gets all developers.
  3. The final method  EnumerateProperties simply enumerates over the reflected properties and prints them out.
public static void TestIT()
{
     TestClass tc = new TestClass( "AValue", "BValue", "CValue" );

     OutputProperties<TestClass>( tc );

     Console.WriteLine( Environment.NewLine );
}

public static void  OutputProperties<T>( T target )
{
     Type targetType = target.GetType();

     PropertyInfo[] propertiesdefaultPublic, propertiesSameAsDefault, propertiesPublicPrivate;

     propertiesdefaultPublic = targetType.GetProperties( );
     propertiesSameAsDefault = targetType.GetProperties( BindingFlags.Instance | BindingFlags.Public );
     propertiesPublicPrivate = targetType.GetProperties( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );

     EnumerateProperties<T>( target, propertiesdefaultPublic, "Default -> ()" );
     EnumerateProperties<T>( target, propertiesSameAsDefault, "Same as Default"   );
     EnumerateProperties<T>( target, propertiesPublicPrivate, "Public And Private"  );
}

private static void EnumerateProperties<T>( T target, PropertyInfo[] properties, string Title )
{
 Console.WriteLine( "{0}------- {1} --------{0}", Environment.NewLine, Title );
 foreach (PropertyInfo prp in properties)
 {
     if (prp.PropertyType == typeof( string ))
         Console.WriteLine( string.Format( "({0}):  {1}", prp.Name, prp.GetValue( target, null ) ) );
 }
}
  • Line 03: Creates the target instance with three values to fill the properties.
  • Line 10: This generic method takes the class type and and actual instance of the type.
  • Line 12: What are we looking at? GetType tells us that.
  • Line 16: Here is the big gotcha! Everyone calls the default incarnation which only returns public properties!
  • Line 17: To achieve what the default does, we have to add two different flags. The key one is instance or we won’t reflect anything!
  • Line 18: This is the call which will get the private and public properties…avoids the gotcha of calling the default.
  • Line 26: We will display the properties and data of the instanced class T.
  • Line 29: Enumerate over the properties of the *TYPE*. This is not the actual instance.
  • Line 31: Only do the strings.
  • Line 32: prp.Name gets the name of the property. While GetValue requires that we pass in the actual instantiated object instance to see an actual values. Null is used because we don’t have an indexed type. Its just a string.

Here is the output:

------- Default -> () --------
(AProp):  AValue
(BProp):  BValue

------- Same as Default --------
(AProp):  AValue
(BProp):  BValue

------- Public And Private --------
(AProp):  AValue
(BProp):  BValue
(CProp):  CValue

To set a value, that is the reverse of GetValue which is found by SetValue below and has the same prerequisites:

private static void SetProperties<T>( T target, PropertyInfo[] properties )
{
    int count = 0;

    foreach (PropertyInfo prp in properties)
        prp.SetValue( target, string.Format( "NewValue{0}", ++count ), null );

}

If we were to do a run by just using the Public and Private properties array as used above gives us the below. The first print out set is what was above with our default values. The second after the call to SetProperties example above which has changed the values:

------- Public And Private --------
(AProp):  AValue
(BProp):  BValue
(CProp):  CValue

Call to SetValue() and the GetValue():

------- Public And Private --------

(AProp):  NewValue1
(BProp):  NewValue2
(CProp):  NewValue3
Share