2010-03-29 20 views
19

Tengo el siguiente dos clases:Conseguir anidada Objeto Propiedad Valor utilizando la reflexión

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

Tengo una instancia de la clase de los empleados de la siguiente manera:

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; 

tengo un método que consigue la propiedad valor basado en el nombre de la propiedad de la siguiente manera:

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

    return prop.GetValue(obj, null); 
} 

El método anterior funciona bien para las llamadas como GetPropertyValue(emp1, "FirstName") pero si intento GetPropertyValue(emp1, "Address.AddressLine1") arroja una excepción porque objType.GetProperty(propertyName); no puede ubicar el valor de la propiedad del objeto anidado. ¿Hay alguna manera de arreglar esto?

Respuesta

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

Empleado El objeto no tiene una sola propiedad llamada "Address.AddressLine1", que tiene una propiedad denominada "Dirección", que a su vez tiene una propiedad denominada "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; 
} 

Gracias, vine aquí en busca de una respuesta al mismo problema. Terminé modificando tu método original para soportar propiedades anidadas. Esto debería ser más sólido que tener que hacer llamadas de métodos anidados que podrían resultar engorrosos para más de 2 niveles anidados.

+0

¿Es esta una respuesta a la otra respuesta? –

+2

esto no funciona para las propiedades de nivel 2 – SyntaxGoonoo

+0

funcionó como un encanto! –

2

obtener las propiedades Nest por ejemplo, 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

una versión modificada de arriba para obtener las propiedades anidadas multinivel

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

Esto funcionará para el nivel 1 y propiedades de objeto de nivel 2, por ejemplo Firstname y 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

Esto funcionará para un número ilimitado de la propiedad anidada.

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

Uso:

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

utilizo este método para obtener los valores de las propiedades (número ilimitado de propiedad anidada) de la siguiente manera:

"Propiedad"

"Address.Street"

"Address.Country.Nombre"

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

Aquí el violín: https://dotnetfiddle.net/PvKRH0

0

hice un método de extensión de tipo para esta proponemos:.

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

Otra variación a tirar por ahí cortos & dulces, soportes propiedades arbitrariamente profundas, maneja valores nulos y propiedades inválidas:

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