如何使用字符串属性路径获取/设置属性值?

Posted

技术标签:

【中文标题】如何使用字符串属性路径获取/设置属性值?【英文标题】: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,需要另一种解决方案。 【参考方案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”通过设置用小写写成大写。

以上是关于如何使用字符串属性路径获取/设置属性值?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用会话属性值执行查询获取和设置数据

如何在核心数据中使用 NSPredicate 从属性之一获取值

如何使用powershell从xml中获取属性值?

如何获取img标签的src属性值

如何获取默认打印机属性设置

如何更改电脑储存路径