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

如何遍历类属性批量获取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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:30:48