C#: How to set or get value of a private or internal property through the Reflection
Quite often in my practice I need to interact with hidden (internal and private) properties of an object. It easily can be done through the Reflection API. The only complication may arise here it’s when a private property is defined in one of the base classes. In this case we have to iterate through the object’s class hierarchy, looking for the property. So, trying to simplify getting and setting values of object’s private and internal properties, I’ve implemented a couple of the methods-extensions listed below. The GetPropertyValue method returns value of a private or internal property, and the SetPropertyValue, in turn, sets value to a private or internal property.
public static class ReflectionHelper { private static PropertyInfo GetPropertyInfo(Type type, string propertyName) { PropertyInfo propInfo = null; do { propInfo = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); type = type.BaseType; } while (propInfo == null && type != null); return propInfo; } public static object GetPropertyValue(this object obj, string propertyName) { if (obj == null) throw new ArgumentNullException("obj"); Type objType = obj.GetType(); PropertyInfo propInfo = GetPropertyInfo(objType, propertyName); if (propInfo == null) throw new ArgumentOutOfRangeException("propertyName", string.Format("Couldn't find property {0} in type {1}", propertyName, objType.FullName)); return propInfo.GetValue(obj, null); } public static void SetPropertyValue(this object obj, string propertyName, object val) { if (obj == null) throw new ArgumentNullException("obj"); Type objType = obj.GetType(); PropertyInfo propInfo = GetPropertyInfo(objType, propertyName); if (propInfo == null) throw new ArgumentOutOfRangeException("propertyName", string.Format("Couldn't find property {0} in type {1}", propertyName, objType.FullName)); propInfo.SetValue(obj, val, null); } }
Below is how to use the methods. Let’s assume we have the following hierarchy of classes:
class SomeBase { private bool IsLimited { get; set; } public SomeBase() { IsLimited = false; } } class SomeClass : SomeBase { private string Str { get; set; } internal int Int { get; set; } public SomeClass() { Str = "initial value"; Int = 0; } }
So, we need to get and set hidden properties’ values from within a project (library) different to the one where the SomeBase and SomeClass are located. A possible code may look like the following:
SomeClass someObj = new SomeClass(); // the Str and Int properties will be found on the first step of iteration, // so, the base class won't be analyzed string currentStrValue = (string)someObj.GetPropertyValue("Str"); int currentIntValue = (int)someObj.GetPropertyValue("Int"); // the IsLimited propertiy will be found on the second step of iteration, // so, the base class will be analyzed as well bool currentBoolValue = (bool)someObj.GetPropertyValue("IsLimited"); // the Str and Int properties will be found on the first step of iteration, // so, the base class won't be analyzed someObj.SetPropertyValue("Str", "brand new value"); someObj.SetPropertyValue("Int", -1); // the IsLimited propertiy will be found on the second step of iteration, // so, the base class will be analyzed as well someObj.SetPropertyValue("IsLimited", true);
Thanks for posting these methods, they’re very useful for debugging.
Very nice. Although you should replace ArgumentOutOfRangeException with InvalidOperationException to correct the semantic meaning of the exception.
In my last comment, prefer MissingMemberException to InvalidOperationException. It’s even more accurate.