You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:39:58