当前位置: 代码迷 >> 综合 >> 自动生成LAMBDA表达式树
  详细解决方案

自动生成LAMBDA表达式树

热度:93   发布时间:2023-10-14 21:49:12.0

为项目中使用所写,根据查询实体自动生成表达式树。支持多个查询,多个字段,多个值。支持(=,like,from,to,in,(多个字段模糊匹配,使用mlike))但必须与查询实体大小写匹配。

一,建立查询实体。

    public class QueryItemModel{/// <summary>/// 关键字,多个key用逗号分隔/// </summary>public string key { get; set; }/// <summary>/// 值,多个value用逗号分隔/// </summary>public string value { get; set; }/// <summary>/// 匹配方式,当key用逗号分隔时,match为mlike/// </summary>public string match { get; set; }}

二,建立,生成查询表达式类。

    public class LambdaUtil{public Expression<Func<T,bool>> QueryBuilder<T>(List<QueryItemModel> propertyNames){if (propertyNames == null) return null;Type elementType = typeof(T);string key = "";string value = "";string match = "";bool IsMultipleKey = false;ParameterExpression param = Expression.Parameter(elementType,"c");BinaryExpression be = Expression.Equal(Expression.Constant(true), Expression.Constant(true));foreach(var item in propertyNames){if (item.value.IsEmpty() && item.key.IsEmpty() && item.match.IsEmpty()) continue;key = item.key;value = item.value;match = item.match.ToLower();List<string> LKeys = key.SplitStringToList();if (LKeys.Count > 1) IsMultipleKey = true;foreach(var k in LKeys){PropertyInfo propertyInfo = elementType.GetProperty(k);var proFullType = propertyInfo.PropertyType;Type propertyType = proFullType.GenericTypeArguments.Length == 0 ? proFullType : proFullType.GenericTypeArguments[0];var valueExpression = match == "in" ? GetValueListConstant(value, propertyType) : GetValueConstant(value, propertyType);MemberExpression propertyExpression = Expression.Property(param, propertyInfo);if (proFullType.Name.Contains("Nullable")) propertyExpression = Expression.Property(propertyExpression,"Value");var falseExpression = (Expression)Expression.Constant(false);if(valueExpression.Value.ToString().Equals("False")){be = Expression.And(be,falseExpression);continue;}switch(match){case "=":be = Expression.And(be, Expression.Equal(propertyExpression, valueExpression));break;case "like":if (propertyType == typeof(string)){var like = Expression.Call(propertyExpression,typeof(string).GetMethod("Contains"),valueExpression);be = Expression.And(be,like);}else{be = Expression.And(be, falseExpression);}break;case "mlike":if (propertyType == typeof(string)){if (IsMultipleKey){be = Expression.Equal(Expression.Constant(false), Expression.Constant(true));IsMultipleKey = !IsMultipleKey;var like = Expression.Call(propertyExpression, typeof(string).GetMethod("Contains"), valueExpression);be = Expression.Or(be, like);}else{var like = Expression.Call(propertyExpression, typeof(string).GetMethod("Contains"), valueExpression);be = Expression.Or(be, like);}}else{be = Expression.And(be, falseExpression);}break;case "in":if(propertyType==typeof(string)||propertyType==typeof(Int32)){var inExp = Expression.Call(valueExpression, valueExpression.Type.GetMethod("Contains", new Type[] { propertyType }), propertyExpression);be = Expression.And(be,inExp);}else{be = Expression.And(be,falseExpression);}break;case "from":if(propertyType.IsValueType){var from = Expression.GreaterThanOrEqual(propertyExpression,valueExpression);be = Expression.And(be,from);}else{be = Expression.And(be, falseExpression);}break;case "to":if (propertyType.IsValueType){var to = Expression.LessThanOrEqual(propertyExpression, valueExpression);be = Expression.And(be, to);}else{be = Expression.And(be, falseExpression);}break;}}}var lambda = Expression.Lambda<Func<T, bool>>(be,param);return lambda;}//生成常量表达式private ConstantExpression GetValueConstant(string value,Type type){string typeName = type.Name.ToLower();ConstantExpression rtn = null;switch(typeName){case "int32":int intValue;if (!int.TryParse(value, out intValue))rtn = Expression.Constant(false);elsertn = Expression.Constant(intValue);break;case "string":rtn = Expression.Constant(value);break;case "float":float fValue;if (!float.TryParse(value, out fValue))rtn = Expression.Constant(false);elsertn = Expression.Constant(fValue);break;case "single":Single sgValue;if (!Single.TryParse(value, out sgValue))rtn = Expression.Constant(false);elsertn = Expression.Constant(sgValue);break;case "decimal":decimal dcValue;if (!decimal.TryParse(value, out dcValue))rtn = Expression.Constant(false);elsertn = Expression.Constant(dcValue);break;case "double":double dbValue;if (!double.TryParse(value, out dbValue))rtn = Expression.Constant(false);elsertn = Expression.Constant(dbValue);break;case "datetime":DateTime dateValue;if (!DateTime.TryParse(value, out dateValue))rtn = Expression.Constant(false);elsertn = Expression.Constant(dateValue);break;default:rtn = Expression.Constant(false);break;}return rtn;}//生成列表常量表达式 实现 In('a','b','c')private ConstantExpression GetValueListConstant(string value,Type type){string typeName = type.GenericTypeArguments.Length == 0 ? type.Name : type.GenericTypeArguments[0].Name;ConstantExpression rtn = null;switch(typeName.ToLower()){case "int32":List<int> dlInt = value.SplitStringToListInt();if (dlInt.Count == 0)rtn = Expression.Constant(false);elsertn = Expression.Constant(dlInt);break;case "string":List<string> dlStr = value.SplitStringToList();if (dlStr.Count == 0)rtn = Expression.Constant(false);elsertn = Expression.Constant(dlStr);break;default:rtn = Expression.Constant(false);break;}return rtn;}}

三,使用方法。

            List<QueryItemModel> lqi = new List<QueryItemModel>{new QueryItemModel{ key="name,title", value="s",match="mlike" },new QueryItemModel{ key="component",value="s",match="like"},new QueryItemModel{ key="sort",value="s",match="="}};LambdaUtil lu = new LambdaUtil();var lambda = lu.QueryBuilder<Sys_menu>(lqi);

lambda里就是生成的表达式树。

mlike时,用OR连接,其它用AND连接。