泛型方法动态生成表达式树 Expression
public string GetGridJSON(TraderInfo model) { IQueryable<TraderInfo> Temp = db.TraderInfo; if (model.LoginAccount != null) { Temp = Temp.Where(X => X.LoginAccount == model.LoginAccount); } if (model.ShopName != null) { Temp = Temp.Where(X => X.ShopName == model.ShopName); } return JsonConvert.SerializeObject(Temp.ToList(), Formatting.Indented, new JsonSerializerSettings() { DateFormatHandling = 0 }); }
这是MVC 项目。 点击查询 执行 GetGridJSON 方法。由于 MVC 规范 name属性可以匹配 模型,如果 不填写 账号 、名称 ,返回的 model 里面 的 账号 、名称属性为 null。 每次都要判断 是否 是 null ,如果是 ,就 查询 所有,否 才能匹配where。
这很不好,如果我的条件 很多 呢? 这样的判断 就 很烦了。
我做了如下如下封装
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Linq.Expressions; namespace EF_DAL { /// <summary> /// 动态生成 表达式树 /// </summary> public class Custom_Expression { /// <summary> /// /// </summary> /// <param name="left"></param> /// <param name="right"></param> /// <returns>Lambda表达式树</returns> public delegate Expression ExpressionEventHandler(Expression left, Expression right); private static BinaryExpression filter = Expression.Equal(Expression.Constant(1), Expression.Constant(1)); /// <summary> /// 自定义Equal方法(允许value为null),value为null 的时候,该查询条件 不会生成 /// </summary> /// <typeparam name="T">实体数据类型</typeparam> /// <param name="columnNames">以逗号分割的列名称</param> /// <param name="values">这些列对应的值</param> /// <returns>返回Lambda表达式,eg:where(Lambda)</returns> public Expression<Func<T, bool>> Custom_Equal<T>(string columnNames, params object[] values) { return Custom_Expression_Common<T>(Equal_result, columnNames, values); } /// <summary> /// 初始化where 1=1 /// </summary> private void Init() { filter = Expression.Equal(Expression.Constant(1), Expression.Constant(1)); } /// <summary> /// 自定义Contains方法(允许value为null),value为null 的时候,该查询条件 不会生成 /// </summary> /// <typeparam name="T">实体数据类型</typeparam> /// <param name="columnNames">以逗号分割的列名称</param> /// <param name="values">这些列对应的值</param> /// <returns>返回Lambda表达式,eg:where(Lambda)</returns> public Expression<Func<T, bool>> Custom_Contain<T>(string columnNames, params object[] values) { return Custom_Expression_Common<T>(Contains_result, columnNames, values); } private Expression Contains_result(Expression left, Expression right) { return Expression.Call(left, typeof(string).GetMethod("Contains"), right); } private Expression Equal_result(Expression left, Expression right) { return Expression.Equal(left, right); } /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="Handler">可以是 Equal、Contains</param> /// <param name="columnNames"></param> /// <param name="values"></param> /// <returns></returns> private Expression<Func<T, bool>> Custom_Expression_Common<T>(ExpressionEventHandler handler, string columnNames, params object[] values) { Init(); var columns = columnNames.Split(','); var param = Expression.Parameter(typeof(T)); for (int i = 0; i < columns.Length; i++) { if (values[i] == null) continue; string columnName = columns[i].ToString(); var value = values[i]; Expression left = Expression.Property(param, typeof(T).GetProperty(columnName)); Expression right = Expression.Constant(value, value.GetType()); Expression result = handler(left, right); filter = Expression.And(filter, result);// where 条件 拼接 } return Expression.Lambda<Func<T, bool>>(filter, param); } } }
直接这样 调用啦!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public string GetGridJSON(TraderInfo model) { EF_DAL.Custom_Expression CE = new EF_DAL.Custom_Expression(); var traderInfoList = db.TraderInfo.Where(CE.Custom_Equal<TraderInfo>("LoginAccount,ShopName", model.LoginAccount, model.ShopName)).ToList(); return JsonConvert.SerializeObject(traderInfoList, Formatting.Indented, new JsonSerializerSettings() { DateFormatHandling = 0 }); }
期待更好的方法。