You need to enable JavaScript to run this app. 如何使用Dynamic Linq从List<IDictionary<string,object>>动态选择指定列
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Dynamic Linq从List<IDictionary<string,object>>动态选择指定列

实现方案

针对你的需求,分两种常用场景给出可直接落地的实现:

场景1:内存集合(IEnumerable<IDictionary<string, object>>)

直接实现扩展方法对每个字典做字段筛选即可:

public static class EnumerableExtensions
{
    /// <summary>
    /// 动态选择字典集合的指定字段
    /// </summary>
    /// <param name="fields">逗号分隔的字段名</param>
    public static IEnumerable<IDictionary<string, object>> Select(this IEnumerable<IDictionary<string, object>> source, string fields)
    {
        if (source == null) throw new ArgumentNullException(nameof(source));
        if (string.IsNullOrWhiteSpace(fields)) throw new ArgumentException("字段列表不能为空", nameof(fields));
        
        var fieldList = fields.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
        
        foreach (var item in source)
        {
            var result = new Dictionary<string, object>();
            foreach (var field in fieldList)
            {
                if (item.TryGetValue(field, out var value))
                {
                    result.Add(field, value);
                }
            }
            yield return result;
        }
    }
}

调用方式和你要求的完全一致:

var result = lstData.Select("Name,School");

返回结果为仅包含指定字段的字典集合。

场景2:数据库IQueryable集合(如EF/EF Core查询)

如果是要对接数据库的IQueryable,为了避免拉取全表再过滤,需要用表达式树动态构建查询逻辑,实现如下:

public static class QueryableExtensions
{
    /// <summary>
    /// 动态构造IQueryable的Select查询,仅返回指定字段
    /// </summary>
    /// <param name="fields">逗号分隔的字段名</param>
    public static IQueryable<IDictionary<string, object>> Select(this IQueryable<IDictionary<string, object>> source, string fields)
    {
        if (source == null) throw new ArgumentNullException(nameof(source));
        if (string.IsNullOrWhiteSpace(fields)) throw new ArgumentException("字段列表不能为空", nameof(fields));
        
        var fieldList = fields.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
        var parameter = Expression.Parameter(typeof(IDictionary<string, object>), "x");
        var addMethod = typeof(Dictionary<string, object>).GetMethod(nameof(Dictionary<string, object>.Add), new[] { typeof(string), typeof(object) })!;
        
        // 构造字典初始化的元素绑定
        var bindings = new List<ElementInit>();
        foreach (var field in fieldList)
        {
            var indexerAccess = Expression.Property(parameter, "Item", Expression.Constant(field));
            bindings.Add(Expression.ElementInit(addMethod, Expression.Constant(field), indexerAccess));
        }
        
        // 构造完整的Lambda表达式
        var dictInit = Expression.ListInit(Expression.New(typeof(Dictionary<string, object>)), bindings);
        var selectLambda = Expression.Lambda<Func<IDictionary<string, object>, IDictionary<string, object>>>(dictInit, parameter);
        
        return source.Select(selectLambda);
    }
}

这个实现会把动态选字段的逻辑直接翻译成SQL的SELECT Name,School FROM xxx,不会查询多余字段,性能和硬编码的Lambda查询一致。

如果需要返回动态强类型对象而非字典,可以搭配ExpandoObject或者反射emit生成动态类使用,常规场景下用字典的实现已经足够简洁高效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 14:27:03