如何通过反射无点符号访问嵌套Model属性并自动更新
反射实现嵌套属性自动Patch(无点符号访问)
现有嵌套模型定义
public class User { public int Id { get; set; } public string Username { get; set; } public byte[] PasswordHash { get; set; } = new byte[0]; public byte[] PasswordSalt { get; set; } = new byte[0]; public Usertype Usertype { get; set; } = Usertype.User; public Details Details { get; set; } } public class Details { public int Id { get; set; } public string Name { get; set; } public string Surname { get; set; } public string Email { get; set; } public DateTime Birthdate { get; set; } public string Address { get; set; } public User User { get; set; } }
需求说明
常规情况下我们通过点符号(如user.Details.Name)访问嵌套属性,但现在需要不使用点符号,通过反射实现以下功能:
- 自动识别
User中的嵌套类型属性(比如Details),无需手动指定类名; - 遍历嵌套类型的属性,将非空/有效值从
User实例更新到UserDTO,实现自动Patch。
完整实现代码
针对原代码框架中的内部foreach逻辑,补充完整实现(同时处理空值、循环引用等场景):
// 用于避免循环引用(比如User和Details互相引用的情况) var processedTypes = new HashSet<Type>(); var properties = userToUpdate.GetType().GetProperties(); foreach(var property in properties) { var value = property.GetValue(userToUpdate); // 跳过空值或默认空字节数组(可根据实际需求调整过滤规则) if(value == null || (value is byte[] byteArr && byteArr.Length == 0)) continue; if(property.PropertyType.IsPrimitive || property.PropertyType == typeof(string) || property.PropertyType.IsEnum) { // 直接赋值基础类型属性到DTO typeof(UserDTO).GetProperty(property.Name)?.SetValue(userDTO, value); } else if(!processedTypes.Contains(property.PropertyType)) { processedTypes.Add(property.PropertyType); // 获取DTO中对应的嵌套属性 var dtoNestedProperty = typeof(UserDTO).GetProperty(property.Name); if(dtoNestedProperty == null) continue; // 若DTO中的嵌套属性未实例化,先创建实例 var dtoNestedValue = dtoNestedProperty.GetValue(userDTO); if(dtoNestedValue == null) { dtoNestedValue = Activator.CreateInstance(dtoNestedProperty.PropertyType); dtoNestedProperty.SetValue(userDTO, dtoNestedValue); } // 遍历嵌套类的所有属性 var nestedProperties = property.PropertyType.GetProperties(); foreach (var nestedProp in nestedProperties) { var nestedValue = nestedProp.GetValue(value); // 跳过空值和循环引用属性(比如Details中的User) if(nestedValue == null || nestedProp.PropertyType == typeof(User)) continue; // 找到DTO嵌套类中对应的属性并赋值 dtoNestedProperty.PropertyType.GetProperty(nestedProp.Name)?.SetValue(dtoNestedValue, nestedValue); } } }
关键逻辑说明
- 空值过滤:提前跳过
null或空字节数组,避免无效赋值操作; - 类型覆盖补充:原代码仅处理基元类型和字符串,补充枚举类型判断,避免遗漏场景;
- 循环引用处理:用
HashSet记录已处理的类型,防止User与Details互相引用导致的无限循环; - DTO嵌套属性实例化:如果
UserDTO中的嵌套属性(如Details)为null,通过Activator.CreateInstance创建实例后再赋值; - 无点符号赋值:全程通过反射获取属性值、定位DTO对应属性,完全不使用点符号访问嵌套属性。
内容的提问来源于stack exchange,提问作者ShadyRaso
相关产品推荐
相关产品推荐

