是否可以解析C# Delegate,从Predicate<T>提取表达式生成SQL WHERE子句?
解析Predicate提取属性及生成SQL WHERE子句的可行方案
Predicate
推荐标准实现方案
调整方法入参类型,将Predicate<Person>替换为Expression<Func<Person, bool>>,表达式树会完整保留你编写的判断逻辑的结构化信息,专门用于逻辑解析、转SQL等场景,修改后的参考代码如下:
internal class Parser { private IEnumerable<Person> people; public Parser(params Person[] people) { this.people = new List<Person>(people); } // 入参改为表达式树类型 public IEnumerable<Person> Parse(Expression<Func<Person, bool>> predicateExpression) { // 解析表达式树生成WHERE子句 string whereClause = ParseExpressionToWhere(predicateExpression.Body); // 可直接用该whereClause拼接SQL执行,也可对接EF等ORM原生的表达式树转SQL能力 return people.Where(predicateExpression.Compile()); } // 简单二元表达式解析示例,仅覆盖基础属性比较场景,复杂逻辑可自行扩展 private string ParseExpressionToWhere(Expression expression) { if (expression is BinaryExpression binaryExp) { // 提取属性名 string propertyName = ((MemberExpression)binaryExp.Left).Member.Name; // 提取比较值 object value = Expression.Lambda(binaryExp.Right).Compile().DynamicInvoke(); // 映射SQL操作符 string op = binaryExp.NodeType switch { ExpressionType.GreaterThan => ">", ExpressionType.Equal => "=", ExpressionType.LessThan => "<", ExpressionType.GreaterThanOrEqual => ">=", ExpressionType.LessThanOrEqual => "<=", ExpressionType.NotEqual => "!=", _ => throw new NotSupportedException($"不支持的操作符{binaryExp.NodeType}") }; // 字符串类型值自动加引号、转义 if (value is string strVal) { value = $"'{strVal.Replace("'", "''")}'"; } return $"{propertyName} {op} {value}"; } throw new NotSupportedException("不支持的表达式类型"); } }
调用方式无需修改,编译器会自动将传入的判断逻辑转换为表达式树:
var parser = new Parser(peopleArray); // 会自动解析生成 WHERE Id > 5 var result = parser.Parse(p => p.Id > 5); // 会自动解析生成 WHERE Name = 'Will' var result2 = parser.Parse(p => p.Name == "Will");
为什么不推荐把Predicate转表达式树的方案
这类方案本质是对已经编译成IL的委托进行反编译推导,只能适配非常简单的无闭包场景,只要逻辑里用到了外部变量、方法调用、嵌套判断,就会解析失败,完全无法满足生产环境转SQL的稳定性要求。
内容的提问来源于stack exchange,提问作者Vic F
相关产品推荐
相关产品推荐

