使用reflection获取嵌套对象属性值

我有以下两个类:

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; } } 

我有一个employee类的实例如下:

  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, "FirstName")但如果我尝试GetPropertyValue(emp1, "Address.AddressLine1")它会抛出exception,因为objType.GetProperty(propertyName); 无法找到嵌套的对象属性值。 有没有办法来解决这个问题?

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

对象Employee没有名为“Address.AddressLine1”的单个属性,它有一个名为“Address”的属性,它本身有一个名为“AddressLine1”的属性。

 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个嵌套级别的繁琐。

我使用此方法从属性(无限数量的嵌套属性)获取值,如下所示:

“属性”

“街道地址”

“Address.Country.Name”

  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

这适用于无限数量的嵌套属性。

 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"); 

获取Nest属性,例如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]); } 

扔掉那里的又一个变种。 Short&sweet,支持任意深度属性,处理空值和无效属性:

 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]); } 

上面的修改版本以获取多级嵌套属性

 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); } } 

这适用于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); } 

我在这个提议的类型上做了一个扩展方法:

 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)); } }