2010-03-29 15 views
19

Mam dwie następujące klasy:Pierwsze obiektu zagnieżdżonego Wartość właściwości przy użyciu odbicia

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

Mam instancję klasy pracowniczej, co następuje:

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; 

Mam metodę, która pobiera właściwość wartość na podstawie nazwy właściwości:

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

    return prop.GetValue(obj, null); 
} 

Powyższa metoda działa prawidłowo w przypadku połączeń jak GetPropertyValue(emp1, "FirstName"), ale jeśli spróbuję GetPropertyValue(emp1, "Address.AddressLine1"), zgłasza wyjątek, ponieważ objType.GetProperty(propertyName); nie jest w stanie zlokalizować zagnieżdżonej wartości właściwości obiektu. Czy istnieje sposób, aby to naprawić?

Odpowiedz

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

Obiekt Pracownik nie posiada jedną właściwość o nazwie „Address.AddressLine1”, ma właściwość o nazwie „Adres”, która sama ma właściwość o nazwie „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; 
} 

Dzięki, przyjechałem tutaj, szukając odpowiedzi na ten sam problem. W efekcie zmodyfikowałem oryginalną metodę obsługi zagnieżdżonych właściwości. Powinno to być bardziej niezawodne niż wykonywanie zagnieżdżonych wywołań metod, które mogą być uciążliwe dla więcej niż 2 poziomów zagnieżdżonych.

+0

Czy jest to odpowiedź na inną odpowiedź? –

+2

to nie działa dla właściwości poziomu 2 – SyntaxGoonoo

+0

działa jak urok! –

2

Get właściwości Nest np 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

zmodyfikowana wersja powyżej, aby uzyskać wielopoziomowych właściwości zagnieżdżonych

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

To będzie działać na poziomie 1 i właściwości obiektu poziomu 2, np Firstname i Address.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

To będzie pracować dla nieograniczonej liczby nieruchomości zagnieżdżonego.

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

Zastosowanie:

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

użyć tej metody, aby uzyskać wartości z właściwości (nieograniczoną liczbę nieruchomości zagnieżdżonego), jak poniżej:

"Property"

"Adres.Street"

"Adres.Kraj.Nazwa”

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

Tutaj Fiddle: https://dotnetfiddle.net/PvKRH0

0

zrobiłem metodę rozszerzenia typu dla tego proponować.

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

Jeszcze inna odmiana wyrzucić tam Short & słodkich, podporach dowolnie głębokie właściwości, obsługuje wartości puste i nieprawidłowe właściwości:

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]); 
} 
Powiązane problemy