如何遍历类属性批量获取CosmosDB去重值生成下拉框?
嘿,你已经找对方向啦!用反射批量处理类属性的思路完美解决了重复54次代码的问题,不过你的当前实现还有可以优化的空间——比如空值过滤、转换成SelectListItem的步骤,以及反射性能的提升,我来给你完善下更完整的方案:
优化后的批量实现代码
首先,我们可以直接通过类型获取属性信息(不需要实例化对象),同时缓存属性信息避免重复反射操作,一步完成空值过滤、去重、排序和SelectListItem转换:
// 缓存FieldMasterInfo的所有属性信息,避免重复反射 var properties = typeof(FieldMasterInfo).GetProperties(); // 存储每个属性对应的下拉列表项 var dropdownDictionary = new Dictionary<string, List<SelectListItem>>(); foreach (var property in properties) { // 提取该属性的所有非空值,去重后排序 var distinctValues = allItems .Select(item => property.GetValue(item)) .Where(value => value != null) // 过滤空值,和你原来的逻辑一致 .Distinct() .OrderBy(value => value.ToString()) // 按文本排序 .ToList(); // 转换成SelectListItem列表 var selectList = distinctValues.Select(value => new SelectListItem { Value = value.ToString(), Text = value.ToString() }).ToList(); dropdownDictionary[property.Name] = selectList; } // 批量将所有下拉列表赋值到ViewBag,自动生成类似FieldIdList的键 foreach (var kvp in dropdownDictionary) { ViewBag[$"{kvp.Key}List"] = kvp.Value; }
关键优化点说明
- 避免重复反射:直接用
typeof(FieldMasterInfo).GetProperties()获取属性,循环里复用缓存的PropertyInfo,不用每次调用GetType().GetProperty,提升性能 - 一站式处理:把空值过滤、去重、排序、转换
SelectListItem合并到一个LINQ查询里,逻辑更紧凑 - 批量赋值ViewBag:不用手动写54次
ViewBag.xxxList,自动根据属性名生成对应的ViewBag键
进阶性能优化(大数据量场景)
如果allItems的数据量很大,反射的GetValue方法可能会有点慢,这时候可以用表达式树编译属性访问器来提升性能,提前缓存访问器避免每次反射开销:
// 静态缓存属性访问器,全局复用 private static readonly Dictionary<PropertyInfo, Func<object, object>> _propertyAccessors = new(); private static Func<object, object> GetPropertyAccessor(PropertyInfo property) { if (_propertyAccessors.TryGetValue(property, out var accessor)) return accessor; // 构建表达式树编译属性访问逻辑 var itemParam = Expression.Parameter(typeof(object), "item"); var castItem = Expression.Convert(itemParam, property.DeclaringType); var propertyAccess = Expression.Property(castItem, property); var castResult = Expression.Convert(propertyAccess, typeof(object)); var accessorLambda = Expression.Lambda<Func<object, object>>(castResult, itemParam); accessor = accessorLambda.Compile(); _propertyAccessors[property] = accessor; return accessor; }
然后在循环里替换GetValue为编译后的访问器:
var propertyAccessor = GetPropertyAccessor(property); var distinctValues = allItems .Select(item => propertyAccessor(item)) .Where(value => value != null) .Distinct() .OrderBy(value => value.ToString()) .ToList();
额外建议
如果你的CosmosDB数据量非常大,在数据库端做去重查询会比拉取全量数据到内存处理更高效——比如针对每个属性执行SELECT DISTINCT c.PropertyName FROM c的CosmosDB SQL查询,批量执行这些查询可以大幅减少内存占用和网络传输量,不过这需要处理异步批量查询的逻辑,适合数据量较大的场景。
内容的提问来源于stack exchange,提问作者cyberwild360
相关产品推荐
相关产品推荐

