Donnerstag, 17. März 2011

Get the property value by its path

/// <summary>

/// walks the property path and gets the value of the property on the object 'value'

/// example: path = "Company.Address[1].City"

/// </summary>

/// <param name="value">object to parse the property value from</param>

/// <param name="path">path to the property</param>

public static object FollowPropertyPath(object value, string path)

{

if (value == null) throw new ArgumentNullException("value");

if (path == null) throw new ArgumentNullException("path");

Type currentType = value.GetType();

object obj = value;

foreach (string propertyName in path.Split('.')) // split property path by "."

{

if (currentType != null)

{

PropertyInfo property = null;

int brackStart = propertyName.IndexOf("["); // parsing out if the property is an indexer property

int brackEnd = propertyName.IndexOf("]");

property = currentType.GetProperty(brackStart > 0 ? propertyName.Substring(0, brackStart) : propertyName);

obj = property.GetValue(obj, null);

if (brackStart > 0) // just for indexer properties

{

string index = propertyName.Substring(brackStart + 1, brackEnd - brackStart - 1); // get the index

// determine type of indexer property. extend the following if other types are required

foreach (Type iType in obj.GetType().GetInterfaces())

{

// http://stackoverflow.com/questions/852233/getting-values-of-a-generic-idictionary-using-reflection

if (iType.IsGenericType && iType.GetGenericTypeDefinition() == typeof(IDictionary<,>))

{

obj = typeof(ReflectorUtil).GetMethod("GetDictionaryElement")

.MakeGenericMethod(iType.GetGenericArguments())

.Invoke(null, new object[] { obj, index });

break;

}

if (iType.IsGenericType && iType.GetGenericTypeDefinition() == typeof(IList<>))

{

obj = typeof(ReflectorUtil).GetMethod("GetListElement")

.MakeGenericMethod(iType.GetGenericArguments())

.Invoke(null, new object[] { obj, index });

break;

}

}

}

// allow for derived properties in the path (property.PropertyType will get the defined type, obj.GetType the actual one)

currentType = obj != null ? obj.GetType() : null; //property.PropertyType;

}

else return null;

}

return obj;

}

public static TValue GetDictionaryElement<TKey, TValue>(IDictionary<TKey, TValue> dict, object index)

{

TKey key = (TKey)Convert.ChangeType(index, typeof(TKey), null);

return dict[key];

}

public static T GetListElement<T>(IList<T> list, object index)

{

return list[Convert.ToInt32(index)];

}