使用反射获取嵌套对象属性值

时间:2022-09-17 02:23:51

I have the following two classes:

我有以下两个班:

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

I have an instance of the employee class as follows:

我有一个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;

I have a method which gets the property value based on the property name as follows:

我有一个基于属性名获取属性值的方法如下:

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

    return prop.GetValue(obj, null);
}

The above method works fine for calls like GetPropertyValue(emp1, "FirstName") but if I try GetPropertyValue(emp1, "Address.AddressLine1") it throws an exception because objType.GetProperty(propertyName); is not able to locate the nested object property value. Is there a way to fix this?

上面的方法适用于GetPropertyValue(emp1,“FirstName”)之类的调用,但如果我尝试GetPropertyValue(emp1,“Address.AddressLine1”),它会抛出异常,因为object . getproperty (propertyName);无法定位嵌套的对象属性值。有办法解决这个问题吗?

9 个解决方案

#1


10  

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

Object Employee doesn't have a single property named "Address.AddressLine1", it has a property named "Address", which itself has a property named "AddressLine1".

Object Employee没有一个名为“Address”的属性。它有一个名为“Address”的属性,它本身具有一个名为“AddressLine1”的属性。

#2


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

Thanks, I came here looking for an answer to the same problem. I ended up modifying your original method to support nested properties. This should be more robust than having to do nested method calls which could end up being cumbersome for more than 2 nested levels.

谢谢,我来这里是想找一个同样的问题的答案。最后我修改了原来的方法以支持嵌套属性。这应该比必须执行嵌套方法调用更健壮,这种方法调用在超过两个嵌套级别时可能会变得麻烦。

#3


7  

I use this method to get the values from properties (unlimited number of nested property) as below:

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

"Property"

“财产”

"Address.Street"

“Address.Street”

"Address.Country.Name"

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

Here the Fiddle: https://dotnetfiddle.net/PvKRH0

这里的小提琴:https://dotnetfiddle.net/PvKRH0

#4


5  

This will work for unlimited number of nested property.

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

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

Usage:

用法:

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

#5


2  

Get Nest properties e.g., Developer.Project.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]);
            }

#6


1  

Yet another variation to throw out there. Short & sweet, supports arbitrarily deep properties, handles null values and invalid properties:

还有另一种变化。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]);
}

#7


0  

A Modified version of above to get the multilevel nested properties

上面的修改版本可以获得多层嵌套属性。

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

#8


0  

This will work for level 1 and level 2 object properties e.g. Firstname and Address.AddressLine1

这将适用于第一级和第二级对象属性,例如Firstname和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);
}

#9


0  

I made an extension method on type for this propose:

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

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


10  

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

Object Employee doesn't have a single property named "Address.AddressLine1", it has a property named "Address", which itself has a property named "AddressLine1".

Object Employee没有一个名为“Address”的属性。它有一个名为“Address”的属性,它本身具有一个名为“AddressLine1”的属性。

#2


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

Thanks, I came here looking for an answer to the same problem. I ended up modifying your original method to support nested properties. This should be more robust than having to do nested method calls which could end up being cumbersome for more than 2 nested levels.

谢谢,我来这里是想找一个同样的问题的答案。最后我修改了原来的方法以支持嵌套属性。这应该比必须执行嵌套方法调用更健壮,这种方法调用在超过两个嵌套级别时可能会变得麻烦。

#3


7  

I use this method to get the values from properties (unlimited number of nested property) as below:

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

"Property"

“财产”

"Address.Street"

“Address.Street”

"Address.Country.Name"

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

Here the Fiddle: https://dotnetfiddle.net/PvKRH0

这里的小提琴:https://dotnetfiddle.net/PvKRH0

#4


5  

This will work for unlimited number of nested property.

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

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

Usage:

用法:

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

#5


2  

Get Nest properties e.g., Developer.Project.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]);
            }

#6


1  

Yet another variation to throw out there. Short & sweet, supports arbitrarily deep properties, handles null values and invalid properties:

还有另一种变化。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]);
}

#7


0  

A Modified version of above to get the multilevel nested properties

上面的修改版本可以获得多层嵌套属性。

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

#8


0  

This will work for level 1 and level 2 object properties e.g. Firstname and Address.AddressLine1

这将适用于第一级和第二级对象属性,例如Firstname和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);
}

#9


0  

I made an extension method on type for this propose:

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

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