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

如何在C#中使用动态属性过滤对象列表

动态属性过滤WarehouseModel列表的修正方案

问题分析

原代码核心错误是尝试用字符串变量propName直接访问对象属性(x.propName),这属于语法错误——C#不支持这种动态属性访问方式。另外,perms.DistinctBy(x => x.FieldName)会丢弃同一属性名下的多个过滤值(比如示例中的"36"和"37"),导致过滤逻辑不完整。

修正方案1:基于反射的基础实现

这种方式简单直接,适合数据量不大的场景:

using ConsoleApp2;

void GetAll()
{
    IEnumerable<WarehouseModel> warehouseModels = new List<WarehouseModel>()
    {
        new WarehouseModel() { Code = "35", Name = "Name 35" },
        new WarehouseModel() { Code = "36", Name = "Name 36" },
        new WarehouseModel() { Code = "37", Name = "Name 37" },
        new WarehouseModel() { Code = "38", Name = "Name 38" },
        new WarehouseModel() { Code = "39", Name = "Name 39" },
        new WarehouseModel() { Code = "40", Name = "Name 40" }
    };

    IEnumerable<PermModel> perms = new List<PermModel>()
    {
        new PermModel() { FieldName = "Code", FieldValue = "36" },
        new PermModel() { FieldName = "Code", FieldValue = "37" }
    };

    var newList = new List<WarehouseModel>();
    // 按FieldName分组,保留同一属性下的所有过滤值
    var permGroups = perms.GroupBy(p => p.FieldName);

    foreach (var group in permGroups)
    {
        // 获取对应的属性信息,先判断是否存在避免空引用
        var propInfo = typeof(WarehouseModel).GetProperty(group.Key);
        if (propInfo == null) continue;

        // 反射获取属性值并与过滤值匹配
        var filtered = warehouseModels.Where(x => 
        {
            // 获取属性值并转为字符串(根据实际属性类型调整转换逻辑)
            var propValue = propInfo.GetValue(x)?.ToString();
            // 匹配当前属性下的任意一个FieldValue
            return group.Any(perm => perm.FieldValue == propValue);
        }).ToList();

        newList.AddRange(filtered);
    }
}

GetAll();

修正方案2:表达式树实现(高性能版)

如果需要处理大量数据,表达式树的性能优于直接反射,因为编译后的表达式是强类型委托:

using ConsoleApp2;
using System.Linq.Expressions;

void GetAll()
{
    IEnumerable<WarehouseModel> warehouseModels = new List<WarehouseModel>()
    {
        new WarehouseModel() { Code = "35", Name = "Name 35" },
        new WarehouseModel() { Code = "36", Name = "Name 36" },
        new WarehouseModel() { Code = "37", Name = "Name 37" },
        new WarehouseModel() { Code = "38", Name = "Name 38" },
        new WarehouseModel() { Code = "39", Name = "Name 39" },
        new WarehouseModel() { Code = "40", Name = "Name 40" }
    };

    IEnumerable<PermModel> perms = new List<PermModel>()
    {
        new PermModel() { FieldName = "Code", FieldValue = "36" },
        new PermModel() { FieldName = "Code", FieldValue = "37" }
    };

    // 构建过滤表达式并编译
    var filterExpression = BuildFilterExpression<WarehouseModel>(perms);
    var newList = warehouseModels.Where(filterExpression.Compile()).ToList();
}

// 通用的过滤表达式构建方法
private static Expression<Func<T, bool>> BuildFilterExpression<T>(IEnumerable<PermModel> perms)
{
    var parameter = Expression.Parameter(typeof(T), "x");
    Expression combinedCondition = Expression.Constant(false);

    var permGroups = perms.GroupBy(p => p.FieldName);
    foreach (var group in permGroups)
    {
        var propInfo = typeof(T).GetProperty(group.Key);
        if (propInfo == null) continue;

        // 构建属性访问表达式
        var propertyAccess = Expression.Property(parameter, propInfo);
        // 将属性值转为字符串(根据实际属性类型调整)
        var toStringCall = Expression.Call(propertyAccess, "ToString", Type.EmptyTypes);

        // 构建当前属性的多值OR条件
        Expression groupCondition = Expression.Constant(false);
        foreach (var perm in group)
        {
            var valueConstant = Expression.Constant(perm.FieldValue);
            var equalsExpr = Expression.Equal(toStringCall, valueConstant);
            groupCondition = Expression.OrElse(groupCondition, equalsExpr);
        }

        // 合并到总条件中
        combinedCondition = Expression.OrElse(combinedCondition, groupCondition);
    }

    return Expression.Lambda<Func<T, bool>>(combinedCondition, parameter);
}

GetAll();

关键修正点

  1. 替换错误的属性访问方式:用反射PropertyInfo.GetValue(x)或表达式树Expression.Property实现动态属性访问
  2. 保留多过滤值:用GroupBy替代DistinctBy,确保同一属性名下的所有FieldValue都参与过滤
  3. 增加异常防护:判断PropertyInfo是否为null,避免因属性名拼写错误导致的空引用异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 09:24:54