如何将字符串转换为C#条件运算符并生成Func<>委托?
C# 字符串运算符转条件委托实现方案
1. 定义Filter实体类
首先定义承载过滤规则的Filter类,包含运算符、比较值和目标属性名:
public class Filter { // 条件运算符字符串(如"=="、"greaterthan"、"contains") public string FilterOperator { get; set; } // 比较值,支持int、double、bool、string等类型 public object Value { get; set; } // 需要过滤的目标对象属性名称 public string TargetProperty { get; set; } }
2. 实现运算符转换与条件委托构建
通过表达式树动态生成条件委托,统一管理字符串到C#运算符的映射:
using System; using System.Linq.Expressions; using System.Collections.Generic; public static class FilterConditionBuilder { // 字符串运算符到表达式树操作的映射表 private static readonly Dictionary<string, Func<Expression, Expression, Expression>> _operatorMappings = new() { { "==", Expression.Equal }, { "!=", Expression.NotEqual }, { "greaterthan", Expression.GreaterThan }, { "greaterthanequal", Expression.GreaterThanOrEqual }, { "lessthan", Expression.LessThan }, { "lessthanequal", Expression.LessThanOrEqual }, { "contains", (left, right) => Expression.Call(left, typeof(string).GetMethod("Contains", new[] { typeof(string) }), right) } }; // 生成单个Filter对应的条件委托 public static Func<T, bool> BuildCondition<T>(Filter filter) { var parameter = Expression.Parameter(typeof(T), "obj"); var propertyExpr = Expression.Property(parameter, filter.TargetProperty); // 将比较值转换为目标属性的类型,确保类型匹配 var convertedValue = Convert.ChangeType(filter.Value, propertyExpr.Type); var valueExpr = Expression.Constant(convertedValue, propertyExpr.Type); if (!_operatorMappings.TryGetValue(filter.FilterOperator.ToLower(), out var exprBuilder)) { throw new NotSupportedException($"不支持的运算符:{filter.FilterOperator}"); } // 构建比较表达式并编译为委托 var conditionExpr = exprBuilder(propertyExpr, valueExpr); return Expression.Lambda<Func<T, bool>>(conditionExpr, parameter).Compile(); } // 组合多个Filter条件,支持and/or逻辑 public static Func<T, bool> CombineConditions<T>(IEnumerable<Filter> filters, string combineOperator = "and") { var conditionList = filters.Select(f => BuildCondition<T>(f)).ToList(); if (!conditionList.Any()) return _ => true; var parameter = Expression.Parameter(typeof(T), "obj"); Expression combinedBody = null; foreach (var condition in conditionList) { var conditionBody = Expression.Invoke(Expression.Constant(condition), parameter); combinedBody = combinedBody == null ? conditionBody : combineOperator.ToLower() switch { "and" => Expression.AndAlso(combinedBody, conditionBody), "or" => Expression.OrElse(combinedBody, conditionBody), _ => throw new NotSupportedException($"不支持的组合运算符:{combineOperator}") }; } return Expression.Lambda<Func<T, bool>>(combinedBody, parameter).Compile(); } }
3. 示例用法
假设我们有一个User类,使用上述工具类构建过滤条件:
public class User { public string Name { get; set; } public int Age { get; set; } public double Score { get; set; } public bool IsActive { get; set; } } // 单个条件示例 var nameFilter = new Filter { FilterOperator = "contains", Value = "John", TargetProperty = nameof(User.Name) }; var nameCondition = FilterConditionBuilder.BuildCondition<User>(nameFilter); var user1 = new User { Name = "John Doe" }; Console.WriteLine(nameCondition(user1)); // 输出: True // 多条件组合示例 var filters = new List<Filter> { new Filter { FilterOperator = "greaterthanequal", Value = 18, TargetProperty = nameof(User.Age) }, new Filter { FilterOperator = "==", Value = true, TargetProperty = nameof(User.IsActive) } }; var combinedCondition = FilterConditionBuilder.CombineConditions<User>(filters, "and"); var user2 = new User { Age = 25, IsActive = true }; Console.WriteLine(combinedCondition(user2)); // 输出: True var user3 = new User { Age = 16, IsActive = true }; Console.WriteLine(combinedCondition(user3)); // 输出: False
核心优势
- 类型安全:通过表达式树和类型转换,避免硬编码不同类型的比较逻辑
- 扩展性强:新增运算符只需在映射表中添加对应规则即可
- 灵活组合:支持多条件的and/or逻辑拼接,满足复杂过滤需求
内容的提问来源于stack exchange,提问作者TheBoubou
相关产品推荐
相关产品推荐

