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

如何利用反射对动态列表按多属性执行GroupBy分组操作

正确实现方案

你的问题出在ForEach没有返回值,无法作为GroupBy的键选择器。GroupBy需要一个能返回可比较相等性的键对象的委托,我们可以通过将多个属性值组合成元组(或匿名类型)来实现分组。

修正后的核心代码

public void ApplySetting<TItem>(List<TItem> myList, MySetting setting)
{
    if (!string.IsNullOrWhiteSpace(setting.Groupby))
    {
        // 分割并清理属性名(去除前后空格)
        var propertyNames = setting.Groupby.Split(',', StringSplitOptions.RemoveEmptyEntries)
                                         .Select(name => name.Trim())
                                         .ToList();

        // 分组:将每个对象的指定属性值组合成数组作为分组键
        var groups = myList.GroupBy(item => 
            propertyNames.Select(propName => GetPropertyValue(propName, item, typeof(TItem)))
                         .ToArray()
        );

        // 此处添加分组后的业务逻辑,比如遍历分组结果
        foreach (var group in groups)
        {
            // 示例:输出分组标识与组内元素数量
            Console.WriteLine($"分组键:{string.Join(", ", group.Key)},元素总数:{group.Count()}");
        }
    }
}

性能优化版本(缓存反射信息)

如果该方法会被频繁调用,每次反射获取属性会产生性能损耗,建议提前缓存PropertyInfo:

// 静态缓存容器,避免重复反射操作
private static readonly Dictionary<Type, Dictionary<string, PropertyInfo>> _propertyCache = new();

public void ApplySetting<TItem>(List<TItem> myList, MySetting setting)
{
    if (!string.IsNullOrWhiteSpace(setting.Groupby))
    {
        var propertyNames = setting.Groupby.Split(',', StringSplitOptions.RemoveEmptyEntries)
                                         .Select(name => name.Trim())
                                         .ToList();

        var itemType = typeof(TItem);
        // 读取或初始化当前类型的属性缓存
        if (!_propertyCache.TryGetValue(itemType, out var propCache))
        {
            propCache = propertyNames.ToDictionary(name => name, name => itemType.GetProperty(name));
            _propertyCache[itemType] = propCache;
        }

        // 用缓存的PropertyInfo直接取值,提升性能
        var groups = myList.GroupBy(item => 
            propertyNames.Select(name => propCache[name]?.GetValue(item))
                         .ToArray()
        );

        // 后续业务逻辑...
    }
}

参考GetPropertyValue实现

如果你的方法还未实现,可参考以下基础版本:

public object GetPropertyValue(string propertyName, object obj, Type objType)
{
    var property = objType.GetProperty(propertyName);
    return property?.GetValue(obj);
}

关键注意事项

  • 分组键需是值类型或重写了Equals和GetHashCode的引用类型,推荐用C# 7.0+的值元组(如(val1, val2))替代数组,因为数组的相等性判断是引用相等,可能导致分组不符合预期。
  • 需处理配置属性名不存在的情况,可添加空判断避免空引用异常。

内容的提问来源于stack exchange,提问作者Nb777

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 20:55:59