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

如何在运行时通过Reflection设置嵌套对象的属性值?

使用Reflection设置嵌套对象属性值

要处理运行时动态创建的嵌套类对象属性赋值,核心思路是递归处理嵌套引用类型,或者解析属性路径逐层赋值。以下是两种实用实现方案:

方案1:递归创建并填充整个对象树

适合从层级化数据源(如嵌套字典)批量构建对象的场景,自动创建所有嵌套对象并赋值:

using System;
using System.Collections.Generic;
using System.Reflection;

public static class ObjectFactory
{
    public static object CreateAndPopulate(Type targetType, Dictionary<string, object> propertyData)
    {
        // 创建目标类型实例
        var instance = Activator.CreateInstance(targetType);
        
        // 遍历所有公共可写实例属性
        foreach (PropertyInfo propInfo in targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            if (!propInfo.CanWrite) continue;
            
            var propType = propInfo.PropertyType;
            // 处理可空值类型,获取底层类型
            var underlyingType = Nullable.GetUnderlyingType(propType);
            var actualType = underlyingType ?? propType;
            
            object valueToSet;
            
            if (actualType.IsValueType || actualType == typeof(string))
            {
                // 值类型/字符串:直接获取并转换类型
                propertyData.TryGetValue(propInfo.Name, out var rawValue);
                valueToSet = rawValue == null ? null : Convert.ChangeType(rawValue, actualType);
            }
            else
            {
                // 引用类型(自定义类):递归创建嵌套对象
                var nestedData = propertyData.TryGetValue(propInfo.Name, out var nestedRaw) 
                    ? nestedRaw as Dictionary<string, object> 
                    : new Dictionary<string, object>();
                valueToSet = CreateAndPopulate(actualType, nestedData);
            }
            
            propInfo.SetValue(instance, valueToSet);
        }
        
        return instance;
    }

    // 泛型包装,方便强类型调用
    public static T CreateAndPopulate<T>(Dictionary<string, object> propertyData)
    {
        return (T)CreateAndPopulate(typeof(T), propertyData);
    }
}

使用示例

假设存在以下嵌套类:

public class Address
{
    public string City { get; set; }
    public string ZipCode { get; set; }
}

public class User
{
    public string Name { get; set; }
    public int? Age { get; set; }
    public Address HomeAddress { get; set; }
}

调用方式:

var data = new Dictionary<string, object>
{
    {"Name", "张三"},
    {"Age", 32},
    {"HomeAddress", new Dictionary<string, object>
        {
            {"City", "杭州"},
            {"ZipCode", "310000"}
        }
    }
};

User user = ObjectFactory.CreateAndPopulate<User>(data);

方案2:按属性路径设置单个嵌套属性

适合单独设置某个深层嵌套属性的场景,自动创建路径上的空对象:

using System;
using System.Reflection;

public static class NestedPropertySetter
{
    public static void SetNestedValue(object target, string propertyPath, object value)
    {
        string[] propertyNames = propertyPath.Split('.');
        object currentObj = target;

        // 遍历到倒数第二个属性,确保所有中间嵌套对象已实例化
        for (int i = 0; i < propertyNames.Length - 1; i++)
        {
            PropertyInfo prop = currentObj.GetType().GetProperty(propertyNames[i]);
            if (prop == null)
                throw new ArgumentException($"未找到属性:{propertyNames[i]}");

            object nestedObj = prop.GetValue(currentObj);
            if (nestedObj == null)
            {
                // 若对象为空,创建实例并赋值
                nestedObj = Activator.CreateInstance(prop.PropertyType);
                prop.SetValue(currentObj, nestedObj);
            }

            currentObj = nestedObj;
        }

        // 设置最终属性的值
        PropertyInfo finalProp = currentObj.GetType().GetProperty(propertyNames[^1]);
        if (finalProp == null)
            throw new ArgumentException($"未找到属性:{propertyNames[^1]}");

        // 转换值的类型以匹配属性类型
        object convertedValue = value == null ? null : Convert.ChangeType(value, finalProp.PropertyType);
        finalProp.SetValue(currentObj, convertedValue);
    }
}

使用示例

User user = Activator.CreateInstance<User>();

// 设置顶层属性
NestedPropertySetter.SetNestedValue(user, "Name", "李四");
// 设置嵌套属性(自动创建HomeAddress实例)
NestedPropertySetter.SetNestedValue(user, "HomeAddress.City", "深圳");
NestedPropertySetter.SetNestedValue(user, "HomeAddress.ZipCode", "518000");

注意事项

  • 性能优化:反射操作开销较高,若需高频调用,可缓存类型的PropertyInfo集合(如用Dictionary<Type, PropertyInfo[]>存储)。
  • 自定义类型转换:Convert.ChangeType仅支持基础类型转换,若需处理自定义类型,需扩展类型转换逻辑。
  • 集合/数组:上述方案未处理集合属性,若需支持,可判断属性类型是否实现IList或ICollection,再创建集合实例并添加元素。

内容的提问来源于stack exchange,提问作者Paul Efford

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:57:21