using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; namespace Zxw.Framework.NetCore.Extensions { /// /// 表达式树常用扩展方法 /// public static class ExpressionExtensions { /// /// 取的 Expression /// > predicate 表达式对应的属性名称 /// 例如:c=>c.Value.Year 侧返回:Value.Year /// /// /// /// /// public static string GetPropertyName(this Expression> predicate) { MemberExpression expression = predicate.Body as MemberExpression; //return expression.Member.Name; //该属性只返回最后一个属性,因此采用下面方法返回。 return expression.ToString().Substring(2); } public static ParameterExpression CreateLambdaParam(string name) { return Expression.Parameter(typeof(T), name); } /// /// 创建linq表达示的body部分 /// public static Expression GenerateBody(this ParameterExpression param, Filter filterObj) { System.Reflection.PropertyInfo property = typeof(T).GetProperty(filterObj.Key); //组装左边 Expression left = Expression.Property(param, property); //组装右边 Expression right = null; if (property.PropertyType == typeof(int)) { right = Expression.Constant(int.Parse(filterObj.Value)); } else if (property.PropertyType == typeof(DateTime)) { right = Expression.Constant(DateTime.Parse(filterObj.Value)); } else if (property.PropertyType == typeof(string)) { right = Expression.Constant(filterObj.Value); } else if (property.PropertyType == typeof(decimal)) { right = Expression.Constant(decimal.Parse(filterObj.Value)); } else if (property.PropertyType == typeof(Guid)) { right = Expression.Constant(Guid.Parse(filterObj.Value)); } else if (property.PropertyType == typeof(bool)) { right = Expression.Constant(filterObj.Value.Equals("1")); } else if (property.PropertyType == typeof(Guid?)) { left = Expression.Property(left, "Value"); right = Expression.Constant(Guid.Parse(filterObj.Value)); } else { throw new Exception("暂不能解析该Key的类型"); } //c.XXX=="XXX" Expression filter = Expression.Equal(left, right); switch (filterObj.Contrast) { case "<=": filter = Expression.LessThanOrEqual(left, right); break; case "<": filter = Expression.LessThan(left, right); break; case ">": filter = Expression.GreaterThan(left, right); break; case ">=": filter = Expression.GreaterThanOrEqual(left, right); break; case "!=": filter = Expression.NotEqual(left, right); break; case "like": filter = Expression.Call(left, typeof(string).GetMethod("Contains", new[] { typeof(string) }), Expression.Constant(filterObj.Value)); break; case "not in": ConstantExpression listExpression = Expression.Constant(filterObj.Value.Split(',').ToList()); //数组 System.Reflection.MethodInfo method = typeof(List).GetMethod("Contains", new[] { typeof(string) }); //Contains语句 filter = Expression.Not(Expression.Call(listExpression, method, left)); break; case "in": ConstantExpression lExp = Expression.Constant(filterObj.Value.Split(',').ToList()); //数组 System.Reflection.MethodInfo methodInfo = typeof(List).GetMethod("Contains", new[] { typeof(string) }); //Contains语句 filter = Expression.Call(lExp, methodInfo, left); break; } return filter; } public static Expression> GenerateTypeBody(this ParameterExpression param, Filter filterObj) { return (Expression>)param.GenerateBody(filterObj); } /// /// 创建完整的lambda /// public static LambdaExpression GenerateLambda(this ParameterExpression param, Expression body) { //c=>c.XXX=="XXX" return Expression.Lambda(body, param); } public static Expression> GenerateTypeLambda(this ParameterExpression param, Expression body) { return (Expression>)param.GenerateLambda(body); } public static Expression AndAlso(this Expression expression, Expression expressionRight) { return Expression.AndAlso(expression, expressionRight); } public static Expression Or(this Expression expression, Expression expressionRight) { return Expression.Or(expression, expressionRight); } public static Expression And(this Expression expression, Expression expressionRight) { return Expression.And(expression, expressionRight); } //系统已经有该函数的实现 //public static IQueryable Where(this IQueryable query, Expression expression) //{ // Expression expr = Expression.Call(typeof(Queryable), "Where", new[] { typeof(T) }, // Expression.Constant(query), expression); // //生成动态查询 // IQueryable result = query.Provider.CreateQuery(expr); // return result; //} public static IQueryable GenerateFilter(this IQueryable query, string filterjson) { if (!string.IsNullOrEmpty(filterjson)) { IEnumerable filters = JsonConvert.DeserializeObject>(filterjson); ParameterExpression param = CreateLambdaParam("c"); Expression result = Expression.Constant(true); foreach (Filter filter in filters) { result = result.AndAlso(param.GenerateBody(filter)); } query = query.Where(param.GenerateTypeLambda(result)); } return query; } /// /// 以特定的条件运行组合两个Expression表达式 /// /// 表达式的主实体类型 /// 第一个Expression表达式 /// 要组合的Expression表达式 /// 组合条件运算方式 /// 组合后的表达式 public static Expression Compose(this Expression first, Expression second, Func merge) { // build parameter map (from parameters of second to parameters of first) Dictionary map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f); // replace parameters in the second lambda expression with parameters from the first Expression secondBody = ParameterRebinder.ReplaceParameters(map, second.Body); // apply composition of lambda expression bodies to parameters from the first expression return Expression.Lambda(merge(first.Body, secondBody), first.Parameters); } /// /// 以 Expression.AndAlso 组合两个Expression表达式 /// /// 表达式的主实体类型 /// 第一个Expression表达式 /// 要组合的Expression表达式 /// 组合后的表达式 public static Expression> And(this Expression> first, Expression> second) { return first.Compose(second, Expression.AndAlso); } /// /// 以 Expression.OrElse 组合两个Expression表达式 /// /// 表达式的主实体类型 /// 第一个Expression表达式 /// 要组合的Expression表达式 /// 组合后的表达式 public static Expression> Or(this Expression> first, Expression> second) { return first.Compose(second, Expression.OrElse); } /// /// 参数重新绑定 /// /// private class ParameterRebinder : ExpressionVisitor { private readonly Dictionary _map; /// /// Initializes a new instance of the class. /// /// The map. private ParameterRebinder(Dictionary map) { _map = map ?? new Dictionary(); } /// /// Replaces the parameters. /// /// The map. /// The exp. /// public static Expression ReplaceParameters(Dictionary map, Expression exp) { return new ParameterRebinder(map).Visit(exp); } /// /// 访问 。 /// /// 要访问的表达式。 /// /// 如果修改了该表达式或任何子表达式,则为修改后的表达式;否则返回原始表达式。 /// protected override Expression VisitParameter(ParameterExpression node) { if (_map.TryGetValue(node, out ParameterExpression replacement)) { node = replacement; } return base.VisitParameter(node); } } } public class Filter { public string Key { get; set; } public string Value { get; set; } public string Contrast { get; set; } } }