C#中如何将字符串转换为LINQ Lambda表达式实现动态谓词查询
动态字符串谓词实现字典列表查询方案
基础背景
需求为使用字符串形式的谓词替代硬编码Lambda表达式,实现对List<Dictionary<string, string>>类型数据源的动态查询,目标是通过传入字段名和判断逻辑,动态拼接谓词完成Where查询。
初始数据源定义
List<Dictionary<string, string>> DataDictionary; void GenerateData() { DataDictionary = new List<Dictionary<string, string>>() { new Dictionary<string, string>() { {"a","1-1" }, {"b","1-2" } }, new Dictionary<string, string>() { {"a","1-3" }, {"b","1-4" } } }; }
原有硬编码查询实现
var data = DataDictionary.AsQueryable(); var result = data.Where(d => d["a"] == "1-1");
目标调用形式
ProcessContext("a", "==\"1-1\"") ProcessContext("a", "!=\"1-1\"") void ProcessContext(string Field, string Context) { string predicate = $"d => d[\"{Field}\"] {Context}"; var result = data.Where(predicate); }
语法错误原因
使用Dynamic LINQ传入完整Lambda字符串触发语法错误,核心原因有两点:
- Dynamic LINQ的Where方法接收字符串谓词时,不需要写Lambda参数声明部分(即不需要写
d =>前缀),直接书写判断表达式即可,表达式默认将序列当前元素作为隐式参数it指代。 - Dynamic LINQ针对
IDictionary类型提供了专属语法支持,既可以通过标准索引器访问值,也可以使用@键名的简化写法直接访问字典对应键的值,不需要按照原生C# Lambda的格式做额外转义。
正确实现方案
首先安装System.Linq.Dynamic.Core NuGet包,之后修改ProcessContext方法即可:
void ProcessContext(string Field, string Context) { // 写法1:通用索引器写法,兼容所有合法键名 // string predicate = $"it[\"{Field}\"] {Context}"; // 写法2:字典专属简化写法,代码更简洁 string predicate = $"@{Field} {Context}"; var result = data.Where(predicate).ToList(); }
效果验证
// 初始化测试数据 GenerateData(); var data = DataDictionary.AsQueryable(); // 原生硬编码写法,返回a值为1-1的1条记录 var result1 = data.Where(d => d["a"] == "1-1").ToList(); // Dynamic LINQ字符串谓词写法,返回结果与result1完全一致,无语法错误 var result2 = data.Where("@a == \"1-1\"").ToList(); // 封装方法调用测试 ProcessContext("a", "==\"1-1\""); // 匹配a值为1-1的记录 ProcessContext("a", "!=\"1-1\""); // 匹配a值不为1-1的记录
提示:如果字典键名包含特殊字符、空格,优先使用
it["键名"]的索引器写法,避免解析异常。
内容的提问来源于stack exchange,提问作者YS R
相关产品推荐
相关产品推荐

