.NET如何从已有类型创建匿名类型并修改指定字段?
动态转换对象类型生成结构一致的简化对象(无需维护目标类)
你可以通过反射+递归类型转换的方式实现需求,无需手动维护简化类,只需要预设类型转换规则,就能自动生成和原对象结构一致的简化动态对象(用ExpandoObject模拟匿名类型的用法)。
核心实现思路
- 用反射遍历原对象的所有公开属性;
- 针对不同类型(布尔、枚举、列表、复杂对象)应用预设转换规则;
- 递归处理嵌套对象和列表元素;
- 用
ExpandoObject存储转换后的属性和值,它可以像匿名类型一样直接访问属性。
完整代码示例
定义原类型和枚举
public enum MyEnum { Value1 = 1, Value2 = 2 } public class MyClass { public string Str1 { get; set; } public bool B1 { get; set; } public MyEnum EnumVal { get; set; } // 扩展属性无需额外修改转换逻辑 public List<MyClass> ChildItems { get; set; } }
转换工具类
using System; using System.Collections; using System.Collections.Generic; using System.Dynamic; using System.Reflection; public static class SimplifiedObjectConverter { // 可扩展的类型转换规则字典 private static readonly Dictionary<Type, Func<object, object>> _typeConverters = new() { { typeof(bool), val => (bool)val ? 1 : 0 }, { typeof(Enum), val => Convert.ToInt32(val) } }; public static dynamic Convert(object source) { if (source == null) return null; var target = new ExpandoObject() as IDictionary<string, object>; var properties = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var prop in properties) { var value = prop.GetValue(source); target[prop.Name] = ConvertValue(value); } return target; } private static object ConvertValue(object value) { if (value == null) return null; var valueType = value.GetType(); // 优先使用预设的转换规则 if (_typeConverters.TryGetValue(valueType, out var converter)) { return converter(value); } // 处理枚举(兜底匹配所有枚举类型) if (valueType.IsEnum) { return Convert.ToInt32(value); } // 处理列表/集合(排除字符串) if (typeof(IEnumerable).IsAssignableFrom(valueType) && valueType != typeof(string)) { var convertedList = new List<object>(); foreach (var item in (IEnumerable)value) { convertedList.Add(ConvertValue(item)); } return convertedList; } // 处理嵌套复杂对象 if (valueType.IsClass && valueType != typeof(string)) { return Convert(value); } // 其他类型直接返回原值 return value; } }
使用示例
// 构造原对象实例 var originalObj = new MyClass { Str1 = "Some rand", B1 = true, EnumVal = MyEnum.Value1, ChildItems = new List<MyClass> { new() { Str1 = "Child 1", B1 = false, EnumVal = MyEnum.Value2 }, new() { Str1 = "Child 2", B1 = true, EnumVal = MyEnum.Value1 } } }; // 转换为简化对象 var simplifiedObj = SimplifiedObjectConverter.Convert(originalObj); // 访问属性和匿名类型用法一致 Console.WriteLine(simplifiedObj.Str1); // 输出: Some rand Console.WriteLine(simplifiedObj.B1); // 输出: 1 Console.WriteLine(simplifiedObj.EnumVal); // 输出: 1 Console.WriteLine(simplifiedObj.ChildItems[0].B1); // 输出: 0
方案优势
- 无需维护目标类:原类新增/修改属性时,转换逻辑自动适配,不用手动同步简化类;
- 规则可扩展:新增类型转换需求时,只需要在
_typeConverters字典中添加对应的转换委托即可; - 支持嵌套结构:自动递归处理嵌套对象和列表,保持原对象的层级结构。
内容的提问来源于stack exchange,提问作者renathy
相关产品推荐
相关产品推荐

