2010-03-29 138 views
19

我有以下兩類:獲取嵌套的對象屬性值使用反射

public class Address 
{ 
    public string AddressLine1 { get; set; } 
    public string AddressLine2 { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public string Zip { get; set; } 
} 

public class Employee 
{ 
    public string FirstName { get; set; } 
    public string MiddleName { get; set; } 
    public string LastName { get; set; } 
    public Address EmployeeAddress { get; set; } 
} 

我有僱員類的一個實例如下:

var emp1Address = new Address(); 
    emp1Address.AddressLine1 = "Microsoft Corporation"; 
    emp1Address.AddressLine2 = "One Microsoft Way"; 
    emp1Address.City = "Redmond"; 
    emp1Address.State = "WA"; 
    emp1Address.Zip = "98052-6399"; 

    var emp1 = new Employee(); 
    emp1.FirstName = "Bill"; 
    emp1.LastName = "Gates"; 
    emp1.EmployeeAddress = emp1Address; 

我有獲取屬性的方法基於屬性名稱的值如下:

public object GetPropertyValue(object obj ,string propertyName) 
{ 
    var objType = obj.GetType(); 
    var prop = objType.GetProperty(propertyName); 

    return prop.GetValue(obj, null); 
} 

上述方法適用於呼叫像GetPropertyValue(emp1, "FirstName")但如果我嘗試GetPropertyValue(emp1, "Address.AddressLine1")它會拋出一個異常,因爲objType.GetProperty(propertyName);無法找到嵌套的對象屬性值。有沒有辦法來解決這個問題?

回答

10
var address = GetPropertyValue(GetPropertyValue(emp1, "Address"), "AddressLine1"); 

對象員工沒有名爲「Address.AddressLine1」一個屬性,它有一個名爲「地址」屬性,它本身有一個名爲「AddressLine1」屬性。

16
public object GetPropertyValue(object obj, string propertyName) 
{ 
    foreach (var prop in propertyName.Split('.').Select(s => obj.GetType().GetProperty(s))) 
     obj = prop.GetValue(obj, null); 

    return obj; 
} 

謝謝,我來到這裏尋找同樣問題的答案。我最終修改了原始方法來支持嵌套屬性。這應該比不得不執行嵌套方法調用更加健壯,這可能最終導致超過2個嵌套級別的麻煩。

+0

這是迴應其他答案嗎? – 2012-10-26 04:51:51

+2

這不適用於2級屬性 – SyntaxGoonoo 2014-08-06 02:58:21

+0

就像一個魅力工作! – 2017-06-01 08:39:28

2

獲取巢性質如Developer.Project.Name

private static System.Reflection.PropertyInfo GetProperty(object t, string PropertName) 
      { 
       if (t.GetType().GetProperties().Count(p => p.Name == PropertName.Split('.')[0]) == 0) 
        throw new ArgumentNullException(string.Format("Property {0}, is not exists in object {1}", PropertName, t.ToString())); 
       if (PropertName.Split('.').Length == 1) 
        return t.GetType().GetProperty(PropertName); 
       else 
        return GetProperty(t.GetType().GetProperty(PropertName.Split('.')[0]).GetValue(t, null), PropertName.Split('.')[1]); 
      } 
0

的上述修改後的版本,以獲得多級嵌套屬性

private static System.Reflection.PropertyInfo GetProperty(object t, string PropertName, out object Value) 
     { 
      Value = ""; 
      var v = t.GetType().GetProperties(); 
      if (t.GetType().GetProperties().Count(p => p.Name == PropertName.Split('.')[0]) == 0) 
       //throw new ArgumentNullException(string.Format("Property {0}, is not exists in object {1}", PropertName, t.ToString())); 
       return null; 
      if (PropertName.Split('.').Length == 1) 
      { 
       var Value1 = t.GetType().GetProperty(PropertName).GetValue(t, null); 
       Value = Value1;//.ToString(); 
       return t.GetType().GetProperty(PropertName); 
      } 
      else 
      { 
       //return GetProperty(t.GetType().GetProperty(PropertName.Split('.')[0]).GetValue(t, null), PropertName.Split('.')[1], out Value); 
       return GetProperty(t.GetType().GetProperty(PropertName.Split('.')[0]).GetValue(t, null), PropertName.Substring(PropertName.IndexOf('.') + 1, PropertName.Length - PropertName.IndexOf('.') - 1), out Value); 
      } 
     } 
0

這將爲1級工作, 2級對象屬性,例如FirstnameAddress.AddressLine1

public object GetPropertyValue(object obj, string propertyName) 
{ 
    object targetObject = obj; 
    string targetPropertyName = propertyName; 

    if (propertyName.Contains('.')) 
    { 
     string[] split = propertyName.Split('.'); 
     targetObject = obj.GetType().GetProperty(split[0]).GetValue(obj, null); 
     targetPropertyName = split[1]; 
    } 

    return targetObject.GetType().GetProperty(targetPropertyName).GetValue(targetObject, null); 
} 
5

這將無限數量的嵌套財產的工作。

public object GetPropertyValue(object obj, string propertyName) 
{ 
    var _propertyNames = propertyName.Split('.'); 

    for (var i = 0; i < _propertyNames.Length; i++) 
    { 
     if (obj != null) 
     { 
      var _propertyInfo = obj.GetType().GetProperty(_propertyNames[i]); 
      if (_propertyInfo != null) 
       obj = _propertyInfo.GetValue(obj); 
      else 
       obj = null; 
     } 
    } 

    return obj; 
} 

用法:

GetPropertyValue(_employee, "Firstname"); 
GetPropertyValue(_employee, "Address.State"); 
GetPropertyValue(_employee, "Address.Country.Name"); 
7

我用這個方法從性能得到的值(嵌套屬性的數量不受限制),如下:

「屬性」

「Address.Street」

「Address.Country。名稱」

public static object GetPropertyValue(object src, string propName) 
    { 
     if (src == null) throw new ArgumentException("Value cannot be null.", "src"); 
     if (propName == null) throw new ArgumentException("Value cannot be null.", "propName"); 

     if(propName.Contains("."))//complex type nested 
     { 
      var temp = propName.Split(new char[] { '.' }, 2); 
      return GetPropertyValue(GetPropertyValue(src, temp[0]), temp[1]); 
     } 
     else 
     { 
      var prop = src.GetType().GetProperty(propName); 
      return prop != null ? prop.GetValue(src, null) : null; 
     } 
    } 

這裏的小提琴:https://dotnetfiddle.net/PvKRH0

0

我的類型進行擴展方法爲這個提議:

public static class TypeExtensions 
{ 
    public static PropertyInfo GetSubProperty(this Type type, string treeProperty, object givenValue) 
    { 
     var properties = treeProperty.Split('.'); 
     var value = givenValue; 

     foreach (var property in properties.Take(properties.Length - 1)) 
     { 
      value = value.GetType().GetProperty(property).GetValue(value); 

      if (value == null) 
      { 
       return null; 
      } 
     } 

     return value.GetType().GetProperty(properties[properties.Length - 1]); 
    } 

    public static object GetSubPropertyValue(this Type type, string treeProperty, object givenValue) 
    { 
     var properties = treeProperty.Split('.'); 
     return properties.Aggregate(givenValue, (current, property) => current.GetType().GetProperty(property).GetValue(current)); 
    } 
} 
1

另一種變扔在那裏短期&甜,支持任意深度的屬性,處理空值和無效屬性:

public static object GetPropertyVal(this object obj, string name) { 
    if (obj == null) 
     return null; 

    var parts = name.Split(new[] { '.' }, 2); 
    var prop = obj.GetType().GetProperty(parts[0]); 
    if (prop == null) 
     throw new ArgumentException($"{parts[0]} is not a property of {obj.GetType().FullName}."); 

    var val = prop.GetValue(obj); 
    return (parts.Length == 1) ? val : val.GetPropertyVal(parts[1]); 
}