C#中如何将对象(含嵌套对象)所有属性值转为字符串数组
问题分析与解决方案
首先看你原代码的几个核心问题:
- 遇到类类型属性时直接
return递归结果,会中断循环,导致只处理第一个嵌套对象就返回,无法收集其他属性的值 - 递归时传递的是
PropertyInfo而非属性的实际值,会引发类型错误 - 仅处理
string类型属性,漏掉了其他类型转字符串的场景 - 没有处理字符串转小写的需求(与你的期望结果匹配)
下面是性能友好的实现,核心优化点是缓存反射的属性信息,避免每次递归都重复获取类型的属性,同时修复递归逻辑、处理所有类型转字符串及小写转换:
优化后的代码
using System.Collections.Concurrent; using System.Reflection; public class ObjectValueExtractor { // 缓存类型的属性信息,避免重复反射操作 private static readonly ConcurrentDictionary<Type, PropertyInfo[]> _propertyCache = new(); public List<string> GetAllStringValuesFromObject(object model, bool toLower = true) { var result = new List<string>(); if (model == null) return result; var type = model.GetType(); // 从缓存获取属性,无缓存则反射并存入缓存 var properties = _propertyCache.GetOrAdd(type, t => t.GetProperties(BindingFlags.Public | BindingFlags.Instance)); foreach (var prop in properties) { var value = prop.GetValue(model); if (value == null) continue; var valueType = value.GetType(); // 值类型或string直接转字符串 if (valueType.IsValueType || valueType == typeof(string)) { var strValue = value.ToString(); if (toLower) strValue = strValue.ToLowerInvariant(); result.Add(strValue); } // 其他引用类型(排除string),递归处理嵌套对象 else if (valueType.IsClass) { result.AddRange(GetAllStringValuesFromObject(value, toLower)); } } return result; } }
使用示例
var extractor = new ObjectValueExtractor(); var apple = new Apple() { Name = "hodor", ReleasedYear = "1999", SweetnessType = "FruitLevel", Color = "Green", StemType = new Stem() { name = "stemar", supplier = "apple" } }; var values = extractor.GetAllStringValuesFromObject(apple); // 输出结果:["hodor", "1999", "fruitlevel", "green", "stemar", "apple"]
性能说明
- 用
ConcurrentDictionary缓存每个类型的PropertyInfo数组,避免每次递归都调用GetType().GetProperties(),大幅减少反射开销 - 递归逻辑正确,不会中断循环,能完整收集所有嵌套对象的属性值
- 处理了
null值,避免空引用异常 - 支持可选的小写转换,完全匹配你的期望结果
内容的提问来源于stack exchange,提问作者DBankx
相关产品推荐
相关产品推荐

