如何使用字符串属性路径获取/设置属性值?
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”通过设置用小写写成大写。以上是关于如何使用字符串属性路径获取/设置属性值?的主要内容,如果未能解决你的问题,请参考以下文章