C#实现从字符串路径获取任意深度的对象属性值
实现通用的深度属性获取扩展方法
看起来你已经找对了方向——用反射遍历点分隔的属性路径就能实现这个需求。我帮你完善这个扩展方法,补上参数校验、空值处理、类型转换等关键逻辑,让它更健壮易用:
完整实现代码
public static class ObjectExtensions { public static T GetValue<T>(this object obj, string fqName) { // 基础参数校验 if (obj == null) throw new ArgumentNullException(nameof(obj)); if (string.IsNullOrWhiteSpace(fqName)) throw new ArgumentException("属性路径不能为空或空白字符串", nameof(fqName)); object currentValue = obj; // 遍历拆分后的属性路径 foreach (var propertyName in fqName.Split('.')) { // 中间属性为null的情况,提前抛出明确异常 if (currentValue == null) throw new InvalidOperationException($"无法访问null引用上的属性 '{propertyName}'"); // 查找当前对象的公共实例属性 var property = currentValue.GetType().GetProperty(propertyName); if (property == null) throw new MissingMemberException(currentValue.GetType().FullName, propertyName); currentValue = property.GetValue(currentValue, null); } // 处理null值到目标类型的转换(支持可空类型) if (currentValue == null) { if (typeof(T).IsValueType && Nullable.GetUnderlyingType(typeof(T)) == null) throw new InvalidCastException($"无法将null转换为非可空值类型 {typeof(T)}"); return default(T); } // 安全转换为目标类型,兼容更多转换场景 try { return (T)Convert.ChangeType(currentValue, typeof(T)); } catch (InvalidCastException ex) { throw new InvalidCastException($"无法将类型 {currentValue.GetType()} 转换为 {typeof(T)}", ex); } } }
关键逻辑说明
- 参数校验:提前拦截空对象、空路径等非法输入,避免后续无意义的反射操作。
- 空值防护:遍历路径时如果中间某个属性为null,立刻抛出明确的异常,方便定位问题。
- 属性查找:默认只查找公共实例属性,如果需要访问非公共属性,可以给
GetProperty添加BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic参数。 - 类型转换:用
Convert.ChangeType替代直接强制转换,支持更多跨类型转换场景(比如string转int、DateTime转string),同时处理了可空类型的null值转换。
使用示例
// 定义示例实体类 public class Person { public string Name { get; set; } public int Age { get; set; } public Person Father { get; set; } } // 调用示例 var me = new Person { Name = "Alex", Age = 30, Father = new Person { Name = "John", Age = 60 } }; string myName = me.GetValue<string>("Name"); // 输出 "Alex" int dadAge = me.GetValue<int>("Father.Age"); // 输出 60 // 尝试获取不存在的属性会抛出MissingMemberException // string invalid = me.GetValue<string>("Father.MiddleName");
可选优化:添加默认值重载
如果希望在出错时返回默认值而非抛出异常,可以添加这个重载方法:
public static T GetValueOrDefault<T>(this object obj, string fqName, T defaultValue = default) { try { return GetValue<T>(obj, fqName); } catch { return defaultValue; } }
内容的提问来源于stack exchange,提问作者AlexCode
相关产品推荐
相关产品推荐

