【问题标题】:How to get/set value of properties using string property paths?如何使用字符串属性路径获取/设置属性值?
【发布时间】:2021-07-02 05:10:36
【问题描述】:

假设我们有一个具有 BasicDetails 类属性的类 Root,然后 basicDetails 有两个属性。一个字符串“Name”和一个名为“CustomAttributes”的动态对象。

我想通过以下方式获取值:

  var root = new Root();
  root.BasicDetails.Name = "Samurai";
  root.BasicDetails.CustomAttributes.phone = "12345";
  string res1 = GetDeepPropertyValue(root, "BasicDetails.CustomAttributes.Phone").ToString();
  string res2 = GetDeepPropertyValue(root, "BasicDetails.Name").ToString();

以下是我尝试过的代码(基于 SO 上的另一个答案):

public static object GetDeepPropertyValue(object src, string propName)
{
    if (propName.Contains('.'))
    {
        string[] Split = propName.Split('.');
        string RemainingProperty = propName.Substring(propName.IndexOf('.') + 1);
        return GetDeepPropertyValue(src.GetType().GetProperty(Split[0]).GetValue(src, null), RemainingProperty);
    }
    else
        return src.GetType().GetProperty(propName).GetValue(src, null);
}

以下是类:

public class Root
{
    public Root()
    {
        BasicDetails = new BasicDetails();
    }
    public BasicDetails BasicDetails { get;set;}
}
public class BasicDetails
{
    public BasicDetails()
    {
        CustomAttributes = new ExpandoObject();
    }
    public string Name { get; set; }
    public dynamic CustomAttributes { get; set; }
}

我尝试过的函数抛出空引用错误。不幸的是,我不太了解反射,所以目前我正在修补猴子。如果有人可以请解释c#如何做到这一点,那就太好了。提前谢谢你。

【问题讨论】:

  • 您好,ExpandoObject 来自哪里?好像不见了
  • @Scircia 这是一个来自System.Dynamic命名空间的内置类
  • 啊@PavelAnikhouski 我明白了。我的坏哈哈。
  • @SamuraiJack,问题来自src.GetType().GetProperty(propName).GetValue(src, null),因为GetProperty 将在ExpandoObject 上返回null,这将导致NullReferenceException。 Drik 在his answer 中解释得很好。您需要更改 GetDeepPropertyValue 的逻辑并在调用 GetValue 之前检查 src.GetType().GetProperty(propName) 是否返回任何内容价值
  • @SamuraiJack,我附上了一个工作代码示例。对于 ExpandoObject,需要另一种解决方案。

标签: c# .net asp.net-core reflection


【解决方案1】:

以下方法从嵌套属性中获取值:

    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
        {
            if (src is ExpandoObject)
            {
                var expando = src as IDictionary<string, object>;

                if (expando != null)
                {
                    object obj;
                    expando.TryGetValue(propName, out obj);
                    return obj;
                }

                return null;
            }
            else
            {
                var prop = src.GetType().GetProperty(propName);
                return prop != null ? prop.GetValue(src, null) : null;
            }
        }
    }

用法:

 string res1 = GetPropertyValue(root, "BasicDetails.CustomAttributes.phone") as string;
 string res2 = GetPropertyValue(root, "BasicDetails.Name") as string;

【讨论】:

  • 完美运行!我知道对于 expando 对象,我需要以不同的方式处理它,但即使存在另一个类对象而不是 ExpandoObject,该解决方案也无法正常工作。我想知道为什么/
  • 你也打错了,属性“phone”通过设置用小写写成大写。
猜你喜欢
  • 2017-07-31
  • 2020-06-20
  • 1970-01-01
  • 1970-01-01
  • 2018-11-28
  • 1970-01-01
  • 2011-08-13
  • 1970-01-01
  • 2019-02-19
相关资源
最近更新 更多