当前位置: 首页 > news >正文

C#表达式树

表达式树(Expression Tree)是C#中表示Lambda表达式或代码的数据结构,允许在运行时分析、修改或执行代码。

动态条件构建

1 构建动态查询条件

using System.Collections.Generic;
using System.Reflection;public class Person
{public int Id { get; set; }public string Name { get; set; }public int Age { get; set; }public string City { get; set; }public decimal Salary { get; set; }public DateTime BirthDate { get; set; }
}public class DynamicConditionBuilder
{// 构建等于条件public static Expression<Func<T, bool>> BuildEqualExpression<T>(string propertyName, object value){// 创建参数表达式ParameterExpression param = Expression.Parameter(typeof(T), "x");// 创建属性表达式MemberExpression property = Expression.Property(param, propertyName);// 如果属性类型与值类型不匹配,尝试转换if (value != null && property.Type != value.GetType()){value = Convert.ChangeType(value, property.Type);}// 创建常量表达式ConstantExpression constant = Expression.Constant(value);// 创建相等表达式BinaryExpression equalExpression = Expression.Equal(property, constant);// 创建Lambda表达式return Expression.Lambda<Func<T, bool>>(equalExpression, param);}// 构建范围条件public static Expression<Func<T, bool>> BuildRangeExpression<T>(string propertyName, object minValue, object maxValue){ParameterExpression param = Expression.Parameter(typeof(T), "x");MemberExpression property = Expression.Property(param, propertyName);// 转换值类型if (minValue != null && property.Type != minValue.GetType())minValue = Convert.ChangeType(minValue, property.Type);if (maxValue != null && property.Type != maxValue.GetType())maxValue = Convert.ChangeType(maxValue, property.Type);ConstantExpression minConstant = Expression.Constant(minValue);ConstantExpression maxConstant = Expression.Constant(maxValue);// 大于等于最小值的条件BinaryExpression greaterThanOrEqual = Expression.GreaterThanOrEqual(property, minConstant);// 小于等于最大值的条件BinaryExpression lessThanOrEqual = Expression.LessThanOrEqual(property, maxConstant);// 组合两个条件(AND)BinaryExpression andExpression = Expression.AndAlso(greaterThanOrEqual, lessThanOrEqual);return Expression.Lambda<Func<T, bool>>(andExpression, param);}// 构建字符串包含条件public static Expression<Func<T, bool>> BuildContainsExpression<T>(string propertyName, string value){ParameterExpression param = Expression.Parameter(typeof(T), "x");MemberExpression property = Expression.Property(param, propertyName);// 获取Contains方法MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });ConstantExpression constant = Expression.Constant(value, typeof(string));// 创建方法调用表达式MethodCallExpression containsCall = Expression.Call(property, containsMethod, constant);return Expression.Lambda<Func<T, bool>>(containsCall, param);}public static void Demo(){// 使用示例var persons = new List<Person>{new Person { Id = 1, Name = "张三", Age = 25, City = "北京" },new Person { Id = 2, Name = "李四", Age = 30, City = "上海" },new Person { Id = 3, Name = "王五", Age = 35, City = "北京" }};// 构建动态条件Expression<Func<Person, bool>> ageCondition = BuildRangeExpression<Person>("Age", 25, 30);Expression<Func<Person, bool>> cityCondition = BuildEqualExpression<Person>("City", "北京");Expression<Func<Person, bool>> nameCondition = BuildContainsExpression<Person>("Name", "");// 编译条件var ageFilter = ageCondition.Compile();var cityFilter = cityCondition.Compile();var nameFilter = nameCondition.Compile();// 应用过滤var ageResult = persons.Where(ageFilter);var cityResult = persons.Where(cityFilter);var nameResult = persons.Where(nameFilter);Console.WriteLine($"年龄在25-30之间: {ageResult.Count()}人");Console.WriteLine($"城市在北京: {cityResult.Count()}人");Console.WriteLine($"姓名包含'张': {nameResult.Count()}人");}
}

2 组合多个条件

public class ComplexConditionBuilder
{// 组合多个条件(AND)public static Expression<Func<T, bool>> And<T>(params Expression<Func<T, bool>>[] expressions){if (expressions == null || expressions.Length == 0)return x => true;if (expressions.Length == 1)return expressions[0];// 从第一个表达式开始var result = expressions[0];for (int i = 1; i < expressions.Length; i++){result = Combine(result, expressions[i], Expression.AndAlso);}return result;}// 组合多个条件(OR)public static Expression<Func<T, bool>> Or<T>(params Expression<Func<T, bool>>[] expressions){if (expressions == null || expressions.Length == 0)return x => false;if (expressions.Length == 1)return expressions[0];var result = expressions[0];for (int i = 1; i < expressions.Length; i++){result = Combine(result, expressions[i], Expression.OrElse);}return result;}// 组合两个表达式private static Expression<Func<T, bool>> Combine<T>(Expression<Func<T, bool>> expr1,Expression<Func<T, bool>> expr2,Func<Expression, Expression, BinaryExpression> combiner){// 创建参数重映射器var parameter = Expression.Parameter(typeof(T));// 创建表达式访问器来重映射参数var leftVisitor = new ParameterReplaceVisitor(expr1.Parameters[0], parameter);var left = leftVisitor.Visit(expr1.Body);var rightVisitor = new ParameterReplaceVisitor(expr2.Parameters[0], parameter);var right = rightVisitor.Visit(expr2.Body);// 组合两个表达式var combined = combiner(left, right);return Expression.Lambda<Func<T, bool>>(combined, parameter);}// 参数替换访问器private class ParameterReplaceVisitor : ExpressionVisitor{private readonly ParameterExpression _oldParameter;private readonly ParameterExpression _newParameter;public ParameterReplaceVisitor(ParameterExpression oldParameter, ParameterExpression newParameter){_oldParameter = oldParameter;_newParameter = newParameter;}protected override Expression VisitParameter(ParameterExpression node){return node == _oldParameter ? _newParameter : node;}}public static void Demo(){// 创建多个条件Expression<Func<Person, bool>> ageCondition = p => p.Age >= 25 && p.Age <= 35;Expression<Func<Person, bool>> cityCondition = p => p.City == "北京";Expression<Func<Person, bool>> salaryCondition = p => p.Salary > 5000;// 组合条件:年龄25-35 AND (城市是北京 OR 工资大于5000)var complexCondition = And(ageCondition,Or(cityCondition, salaryCondition));Console.WriteLine($"复杂条件: {complexCondition}");}
}

3 动态排序实现

public class DynamicOrderByBuilder
{// 动态构建排序表达式public static IQueryable<T> ApplyOrderBy<T>(IQueryable<T> query,string propertyName,bool descending = false){// 验证属性是否存在var propertyInfo = typeof(T).GetProperty(propertyName);if (propertyInfo == null)throw new ArgumentException($"属性 '{propertyName}' 在类型 '{typeof(T).Name}' 中不存在");// 创建参数表达式ParameterExpression param = Expression.Parameter(typeof(T), "x");// 创建属性表达式MemberExpression property = Expression.Property(param, propertyInfo);// 创建Lambda表达式LambdaExpression lambda = Expression.Lambda(property, param);// 获取排序方法名string methodName = descending ? "OrderByDescending" : "OrderBy";// 反射调用OrderBy方法var method = typeof(Queryable).GetMethods().First(m => m.Name == methodName && m.GetParameters().Length == 2).MakeGenericMethod(typeof(T), propertyInfo.PropertyType);return (IQueryable<T>)method.Invoke(null, new object[] { query, lambda });}// 多列动态排序public static IQueryable<T> ApplyOrderBy<T>(IQueryable<T> query,params (string propertyName, bool descending)[] sortings){var result = query;foreach (var sorting in sortings){result = ApplyOrderBy(result, sorting.propertyName, sorting.descending);}return result;}
}// 使用扩展方法形式
public static class QueryableExtensions
{public static IQueryable<T> OrderByDynamic<T>(this IQueryable<T> query,string propertyName,bool descending = false){return DynamicOrderByBuilder.ApplyOrderBy(query, propertyName, descending);}
}

4 动态选择(Select)表达式

public class DynamicSelectBuilder
{// 创建匿名类型投影public static Expression<Func<T, object>> BuildSelectExpression<T>(params string[] propertyNames){// 创建参数表达式ParameterExpression param = Expression.Parameter(typeof(T), "x");// 创建属性表达式列表List<MemberBinding> bindings = new List<MemberBinding>();List<Type> propertyTypes = new List<Type>();foreach (var propName in propertyNames){var propertyInfo = typeof(T).GetProperty(propName);if (propertyInfo == null)continue;// 创建属性访问表达式MemberExpression propertyExpr = Expression.Property(param, propertyInfo);// 创建成员绑定
            bindings.Add(Expression.Bind(propertyInfo, propertyExpr));propertyTypes.Add(propertyInfo.PropertyType);}// 如果没有有效属性,返回nullif (bindings.Count == 0)return null;// 创建匿名类型var anonymousType = CreateAnonymousType(propertyNames, propertyTypes);// 创建匿名类型构造函数NewExpression newExpr = Expression.New(anonymousType);// 创建成员初始化表达式MemberInitExpression initExpr = Expression.MemberInit(newExpr, bindings);// 创建Lambda表达式return Expression.Lambda<Func<T, object>>(Expression.Convert(initExpr, typeof(object)), param);}private static Type CreateAnonymousType(string[] propertyNames,Type[] propertyTypes){// 使用反射创建匿名类型var assemblyName = new AssemblyName("DynamicTypes");var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);var moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");var typeBuilder = moduleBuilder.DefineType("AnonymousType",TypeAttributes.Public | TypeAttributes.Class |TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit);// 添加属性FieldInfo[] fields = new FieldInfo[propertyNames.Length];PropertyInfo[] properties = new PropertyInfo[propertyNames.Length];for (int i = 0; i < propertyNames.Length; i++){// 添加字段fields[i] = typeBuilder.DefineField($"_{propertyNames[i]}",propertyTypes[i],FieldAttributes.Private);// 添加属性properties[i] = typeBuilder.DefineProperty(propertyNames[i],PropertyAttributes.HasDefault,propertyTypes[i],null);// 定义get方法MethodBuilder getMethod = typeBuilder.DefineMethod($"get_{propertyNames[i]}",MethodAttributes.Public | MethodAttributes.SpecialName |MethodAttributes.HideBySig,propertyTypes[i],Type.EmptyTypes);ILGenerator getIL = getMethod.GetILGenerator();getIL.Emit(OpCodes.Ldarg_0);getIL.Emit(OpCodes.Ldfld, fields[i]);getIL.Emit(OpCodes.Ret);// 定义set方法MethodBuilder setMethod = typeBuilder.DefineMethod($"set_{propertyNames[i]}",MethodAttributes.Public | MethodAttributes.SpecialName |MethodAttributes.HideBySig,null,new Type[] { propertyTypes[i] });ILGenerator setIL = setMethod.GetILGenerator();setIL.Emit(OpCodes.Ldarg_0);setIL.Emit(OpCodes.Ldarg_1);setIL.Emit(OpCodes.Stfld, fields[i]);setIL.Emit(OpCodes.Ret);// 将方法与属性关联
            properties[i].SetGetMethod(getMethod);properties[i].SetSetMethod(setMethod);}// 定义构造函数ConstructorBuilder ctorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public,CallingConventions.Standard,propertyTypes);ILGenerator ctorIL = ctorBuilder.GetILGenerator();// 调用基类构造函数
        ctorIL.Emit(OpCodes.Ldarg_0);ctorIL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));// 初始化字段for (int i = 0; i < propertyTypes.Length; i++){ctorIL.Emit(OpCodes.Ldarg_0);ctorIL.Emit(OpCodes.Ldarg_S, i + 1);ctorIL.Emit(OpCodes.Stfld, fields[i]);}ctorIL.Emit(OpCodes.Ret);return typeBuilder.CreateType();}public static void Demo(){var persons = new List<Person>{new Person { Id = 1, Name = "张三", Age = 25 },new Person { Id = 2, Name = "李四", Age = 30 }};// 动态选择Id和Name属性Expression<Func<Person, object>> selectExpr = BuildSelectExpression<Person>("Id", "Name");if (selectExpr != null){var func = selectExpr.Compile();var results = persons.Select(func);foreach (var result in results){Console.WriteLine($"结果: {result}");}}}
}

 

http://www.jsqmd.com/news/113888/

相关文章:

  • 2025年年终绿色工厂咨询公司推荐榜:专业对比与实用选择指南 - 品牌推荐
  • 2025年年终绿色工厂咨询公司推荐排行榜单:五家专业服务机构深度对比与选择指南 - 品牌推荐
  • 2025年零食店加盟权威品牌排行榜,五大精选加盟品牌推荐 - mypinpai
  • 2025年零食店加盟权威品牌排行榜,五大精选加盟品牌推荐 - mypinpai
  • 2025年镇江点茶课程机构权威推荐榜单:学点茶/点茶证书/点茶培训源头机构精选 - 品牌推荐官
  • 2025年青岛正亚机械权威解析:全球方便食品装备产业口碑深度剖析 - 品牌推荐
  • 2025靠谱的超低温液压油生产厂家TOP5推荐:甄选服务商助力设备高效运维 - 工业推荐榜
  • 拉普拉斯绝对值和,为什么比方差更敏感?
  • 2025年12月认证齐全!知名的电缆生产厂家推荐TOP榜单前十,电缆生产厂家推荐 - 品牌2026
  • 2025年年终中国母线槽生产厂家推荐排行榜单对比与评测 - 品牌推荐
  • 2025年青岛正亚机械深度解析与权威盘点:全球方便食品装备行业的技术实力与市场口碑分析 - 品牌推荐
  • 2025年乌鲁木齐墓地公司权威推荐榜单:殡葬一条龙/殡葬用品/公墓服务公司精选 - 品牌推荐官
  • 2025年年终小巨人申请代理公司推荐排行榜单对比与评价分析 - 品牌推荐
  • 2025年年终小巨人申请代理公司推荐排行榜:五家服务机构深度对比与选择指南 - 品牌推荐
  • 2025年年终乌冬面生产线工厂排行榜推荐:五家优质企业综合对比与选购指南 - 品牌推荐
  • 2025年青岛正亚机械权威解析:全球方便食品装备产业口碑与评价深度观察 - 品牌推荐
  • 河南省三门峡市自建房设计公司/机构权威测评推荐排行榜 - 苏木2025
  • 河南省平顶山市自建房设计公司/机构权威测评推荐排行榜 - 苏木2025
  • 2025年年终小巨人申请代理公司推荐排行榜单对比与评测分析 - 品牌推荐
  • 2025年衡水出租救护车公司权威推荐榜单:长途救护车出租/跨市救护车出租/本地救护车出租服务机构精选 - 品牌推荐官
  • 2025年青岛正亚机械深度解析:全球方便食品装备产业口碑与市场评价分析 - 品牌推荐
  • 2025年年终挂面生产线工厂综合对比与推荐排行榜单深度解析 - 品牌推荐
  • 2025年年终中国母线槽生产厂家综合实力对比与推荐排行榜单 - 品牌推荐
  • 2025年度雅思培训机构排名:羊驼雅思课程评价、羊驼雅思培训靠谱吗全解析 - mypinpai
  • ZYNQ DMA to UDP 数据传输系统设计文档 - 详解
  • 2025年年终中国母线槽生产厂家推荐排行榜:五家优质企业综合对比与选购指南 - 品牌推荐
  • 2025年十大长期防锈油公司排行榜,专业防锈油厂家推荐 - 工业推荐榜
  • 2025年年终中国母线槽生产厂家推荐排行榜:五强实力对比与选择指南 - 品牌推荐
  • 2025年国内齿轮油靠谱生产厂家推荐:汽车齿轮油专业供应商都有哪些? - myqiye
  • 2025年年终乌冬面生产线工厂排行榜推荐:五家优质工厂综合对比与选择指南 - 品牌推荐