Best way to get sub properties using GetProperty

后端 未结 6 662
南方客
南方客 2020-12-08 10:21
public class Address
{
    public string ZipCode {get; set;}
}

public class Customer
{
    public Address Address {get; set;}
}

how can I access e

6条回答
  •  自闭症患者
    2020-12-08 10:58

    Jon Skeet's answer is fine, I had to extend his method a bit though, in order to account for derived instances within the property path:

    public static class ReflectorUtil
    {
        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('.'))
            {
                if (currentType != null)
                {
                    PropertyInfo property = null;
                    int brackStart = propertyName.IndexOf("[");
                    int brackEnd = propertyName.IndexOf("]");
    
                    property = currentType.GetProperty(brackStart > 0 ? propertyName.Substring(0, brackStart) : propertyName);
                    obj = property.GetValue(obj, null);
    
                    if (brackStart > 0)
                    {
                        string index = propertyName.Substring(brackStart + 1, brackEnd - brackStart - 1);
                        foreach (Type iType in obj.GetType().GetInterfaces())
                        {
                            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;
                            }
                        }
                    }
    
                    currentType = obj != null ? obj.GetType() : null; //property.PropertyType;
                }
                else return null;
            }
            return obj;
        }
    
        public static TValue GetDictionaryElement(IDictionary dict, object index)
        {
            TKey key = (TKey)Convert.ChangeType(index, typeof(TKey), null);
            return dict[key];
        }
    
        public static T GetListElement(IList list, object index)
        {
            return list[Convert.ToInt32(index)];
        }
    
    }
    

    Using property.PropertyType will get you the property type defined on the obj class, while using obj.GetType() will get you the actual type of the property's instance.

    EDIT: @Oliver - you're absolutely right, thanks for noting that. I adjusted the method to allow for generic Lists and Dictionaries. While I don't like the parsing part, I used Marc Gravell's clever idea in this thread to get the indexer property's values.

提交回复
热议问题