using System.Linq.Expressions; namespace CmsQueryExtensions.Extension { internal class ParameterRebinder : ExpressionVisitor { private readonly Dictionary map; public ParameterRebinder(Dictionary map) { this.map = map ?? new Dictionary(); } public static Expression ReplaceParameters(Dictionary map, Expression exp) { return new ParameterRebinder(map).Visit(exp); } protected override Expression VisitParameter(ParameterExpression p) { ParameterExpression replacement; if (map.TryGetValue(p, out replacement)) { p = replacement; } return base.VisitParameter(p); } } internal static class PredicateExtensions { public static Expression> True() { return f => true; } public static Expression> False() { return f => false; } public static Expression Compose(this Expression first, Expression second, Func merge) { // build parameter map (from parameters of second to parameters of first) var 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 var 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); } //public static Expression> And(this Expression> first, Expression> second) //{ // return first.Compose(second, Expression.And); //} public static Expression> AndAlso(this Expression> first, Expression> second) { return first.Compose(second, Expression.AndAlso); } public static Expression> Or(this Expression> first, Expression> second) { return first.Compose(second, Expression.Or); } /// /// 拼接成 c.Name.contains("1111")||c.Name.Contains("2222")||c.Name.Contains("3333")) 形式 /// /// /// /// /// public static Expression> GetConditionExpression(string[] options, string fieldName) { ParameterExpression left = Expression.Parameter(typeof(T), "c");//c=> Expression expression = Expression.Constant(false); foreach (var optionName in options) { Expression right = Expression.Call ( Expression.Property(left, typeof(T).GetProperty(fieldName)), //c.DataSourceName typeof(string).GetMethod("Contains", new Type[] { typeof(string) }),// 反射使用.Contains()方法 Expression.Constant(optionName) // .Contains(optionName) ); expression = Expression.Or(right, expression);//c.DataSourceName.contain("") || c.DataSourceName.contain("") } Expression> finalExpression = Expression.Lambda>(expression, new ParameterExpression[] { left }); return finalExpression; } ///// ///// (模糊查询)拼接成 c.Name.contains("1111")||c.Code.Contains("1111")||c.Address.Contains("1111")) 形式 ///// ///// ///// ///// ///// //public static Expression> GetConditionExpressionForFuzzyQuery(string[] fieldNames, string fieldValue) //{ // try // { // ParameterExpression left = Expression.Parameter(typeof(T), "c");//c=> // Expression expression = Expression.Constant(true);//修改为true,解决公共模糊查询的问题 // foreach (var fieldName in fieldNames) // { // try // { // Expression right = Expression.Call // ( // Expression.Property(left, typeof(T).GetProperty(fieldName)), //c.DataSourceName // typeof(string).GetMethod("Contains", new Type[] { typeof(string) }),// 反射使用.Contains()方法 // Expression.Constant(fieldValue) // .Contains(fieldValue) // ); // expression = Expression.Or(right, expression);//c.AAA.contain("") || c.BBB.contain("") // } // catch (Exception ex) // { // throw new Exception($"参数{fieldName}匹配关键字查询时失败:" + ex.Message); // } // } // Expression> finalExpression // = Expression.Lambda>(expression, new ParameterExpression[] { left }); // return finalExpression; // } // catch (Exception) // { // throw; // } //} /// /// (模糊查询)拼接成 c.Name.contains("1111")||c.Code.Contains("1111")||c.Address.Contains("1111")) 形式 /// /// /// /// /// public static Expression> GetConditionExpressionForFuzzyQuery(string[] fieldNames, string fieldValue) { if (fieldNames == null || fieldNames.Length == 0) { throw new ArgumentException("至少需要指定一个字段名", nameof(fieldNames)); } if (string.IsNullOrEmpty(fieldValue)) { // 空值查询返回总是返回false的表达式 var parameter2 = Expression.Parameter(typeof(T), "c"); return Expression.Lambda>(Expression.Constant(false), parameter2); } ParameterExpression parameter = Expression.Parameter(typeof(T), "c"); Expression? expression = null; foreach (var fieldName in fieldNames) { try { var propertyInfo = typeof(T).GetProperty(fieldName); if (propertyInfo == null) { throw new ArgumentException($"类型 {typeof(T).Name} 不包含属性 {fieldName}"); } if (propertyInfo.PropertyType != typeof(string)) { throw new ArgumentException($"属性 {fieldName} 不是字符串类型"); } var propertyAccess = Expression.Property(parameter, propertyInfo); var containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) }); var searchExpression = Expression.Call(propertyAccess, containsMethod!, Expression.Constant(fieldValue)); expression = expression == null ? searchExpression : Expression.OrElse(expression, searchExpression); } catch (Exception ex) { throw new InvalidOperationException($"处理字段 {fieldName} 时出错", ex); } } if (expression == null) { // 如果所有字段都无效,返回总是返回false的表达式 return Expression.Lambda>(Expression.Constant(false), parameter); } return Expression.Lambda>(expression, parameter); } /// /// (精准查询)拼接成 c.Name.equals("1111")||c.Code.equals("1111")||c.Address.equals("1111")) 形式 /// /// /// /// /// public static Expression> GetConditionExpressionForPreciseQuery(string[] fieldNames, string fieldValue) { ParameterExpression left = Expression.Parameter(typeof(T), "c");//c=> Expression expression = Expression.Constant(false); foreach (var fieldName in fieldNames) { Expression right = Expression.Call ( Expression.Property(left, typeof(T).GetProperty(fieldName)), //c.DataSourceName typeof(string).GetMethod("Equals", new Type[] { typeof(string) }),// 反射使用.Equals()方法 Expression.Constant(fieldValue) // .Equals(fieldValue) ); expression = Expression.Or(right, expression);//c.AAA.equals("") || c.BBB.equals("") } Expression> finalExpression = Expression.Lambda>(expression, new ParameterExpression[] { left }); return finalExpression; } public static Expression> GetConditionExpressionForHighFieldByAnd(List hsmList) { var whereHelper = new WhereHelper(); foreach (var field in hsmList) { switch (field.filterMode) { case SearchFilterModeEnum.不等于: whereHelper.NotEqual(field.fieldName, field.fieldValue); break; case SearchFilterModeEnum.大于: whereHelper.GreaterThan(field.fieldName, field.fieldValue); break; case SearchFilterModeEnum.大于等于: whereHelper.GreaterThanOrEqual(field.fieldName, field.fieldValue); break; case SearchFilterModeEnum.小于: whereHelper.LessThan(field.fieldName, field.fieldValue); break; case SearchFilterModeEnum.小于等于: whereHelper.LessThanOrEqual(field.fieldName, field.fieldValue); break; case SearchFilterModeEnum.模糊查询: whereHelper.Contains(field.fieldName, field.fieldValue); break; case SearchFilterModeEnum.精准查询: whereHelper.Equal(field.fieldName, field.fieldValue); break; } } Expression> finalExpression = Expression.Lambda>(whereHelper.filter, new ParameterExpression[] { whereHelper.param }); return finalExpression; } public static Expression> GetConditionExpressionForHighFieldByAnd(List hsmForDatetimeList) { var whereHelper = new WhereHelper(); foreach (var field in hsmForDatetimeList) { whereHelper.GreaterThanOrEqual(field.fieldName, field.start_fieldValue); whereHelper.LessThanOrEqual(field.fieldName, field.end_fieldValue); } Expression> finalExpression = Expression.Lambda>(whereHelper.filter, new ParameterExpression[] { whereHelper.param }); return finalExpression; } /// /// 日期范围OR连接 /// /// /// /// public static Expression> GetConditionExpressionForHighDateTimeRangeFieldByOr(List hsmForDatetimeList) { Expression> finalExpression = null; var whereHelper = new WhereHelper(); foreach (var field in hsmForDatetimeList) { whereHelper.GreaterThanOrEqual(field.fieldName, field.start_fieldValue); whereHelper.LessThanOrEqual(field.fieldName, field.end_fieldValue); finalExpression = Expression.Lambda>(whereHelper.filter, new ParameterExpression[] { whereHelper.param }); finalExpression = finalExpression.Or(finalExpression); } return finalExpression; } } }