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); } // 如果没有有效属性,返回null if (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}"); } } } }
本文来自博客园,作者:CelonY,转载请注明原文链接:https://www.cnblogs.com/CelonY/p/19374788
浙公网安备 33010602011771号