using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Linq.Expressions; namespace Model { [NotMapped] public class FilterInfo { /// <summary> /// 字段名称 /// </summary> public string FieldName { get; set; } /// <summary> /// 字段值 /// </summary> public object FieldValue { get; set; } /// <summary> /// 操作符 /// </summary> public FilterOperator Operator { get; set; } /// <summary> /// 构建表达式 /// </summary> /// <returns></returns> public Func<T, bool> BuildExpression<T>() { var constEexp = Expression.Constant(FieldValue, this.FieldValue.GetType()); var paramExp = Expression.Parameter(typeof(T), "x"); Expression expLeft = null; var tp = typeof(T); //基元类型直接去paramExp,自定义类型取PropExp if (!tp.IsPrimitive && tp != typeof(string)) { expLeft = (Expression)Expression.Property(paramExp, FieldName); } else { expLeft = paramExp; } Expression bExp = null; switch (Operator) { case FilterOperator.GreaterThan://> bExp = Expression.GreaterThan(expLeft, constEexp); break; case FilterOperator.GreaterThanOrEqual://>= bExp = Expression.GreaterThanOrEqual(expLeft, constEexp); break; case FilterOperator.LessThan://< bExp = Expression.LessThan(expLeft, constEexp); break; case FilterOperator.LessThanOrEqul://<= bExp = Expression.LessThanOrEqual(expLeft, constEexp); break; case FilterOperator.OrElse://!= bExp = Expression.NotEqual(expLeft, constEexp); break; case FilterOperator.Like: if (this.FieldValue.GetType() != typeof(string)) { throw (new Exception("Like只能用于string类型的字段操作")); } bExp = Expression.Call(typeof(FilterInfo).GetMethod("Contains", new Type[] { typeof(string), typeof(string) }), expLeft, constEexp); break; default://= bExp = Expression.Equal(expLeft, constEexp); break; } var exp = Expression.Lambda<Func<T, bool>>(bExp, paramExp); Console.WriteLine(exp); return exp.Compile(); } /// <summary> /// 用该静态方法实现like /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static bool Contains(string a, string b) { if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b)) { return false; } return a.Contains(b); } } /// <summary> /// 操作符枚举 /// </summary> public enum FilterOperator { /// <summary> /// > /// </summary> GreaterThan, /// <summary> /// = /// </summary> Equal, /// <summary> /// < /// </summary> LessThan, /// <summary> /// <= /// </summary> LessThanOrEqul, /// <summary> /// >= /// </summary> GreaterThanOrEqual, /// <summary> /// != /// </summary> OrElse, /// <summary> /// contain /// </summary> Like } }
使用该表达式生成器,可以生成简单的匿名查询函数来过滤查询结果。如果我们在项目中用了EF框架,就可以在业务层中通过这个类来构建查询条件然后传到DAL层来执行,使用方法如下:
//整形数组查询 int[] nums = { 5, 4, 2, 2, 9, 8, 6, 7, 2, 0 }; FilterInfo filterInt = new FilterInfo() { FieldName = "x", FieldValue = 2, Operator = FilterOperator.LessThanOrEqul }; var intFunc = filterInt.BuildExpression<int>(); var r = nums.Where(intFunc); foreach (var i in r) { Console.WriteLine(i); } Console.WriteLine("int array search complete"); //字符串数组查询 string[] strArray = { "string1", "string11", "string2", "string2134", "stringOld" }; FilterInfo f = new FilterInfo() { FieldName = "x", FieldValue = "1", Operator = FilterOperator.Like }; var fc = f.BuildExpression<string>(); strArray.Where(fc).ToList().ForEach(s => Console.WriteLine(s)); //对象列表查询 List<Org> orglist = new List<Org>(); orglist.Add(new Org() { Guid = Guid.NewGuid().ToString(), Name = "spring" }); for (int i = 0; i < 10; i++) { orglist.Add(new Org() { Guid = Guid.NewGuid().ToString(), Name = "orgName" + Guid.NewGuid().ToString() }); } FilterInfo filter = new FilterInfo() { FieldName = "Name", FieldValue = "Name", Operator = FilterOperator.Like }; var func = filter.BuildExpression<Org>(); var orgSearchList = orglist.Where(func); foreach (var o in orgSearchList) { Console.WriteLine(o.Name); } Console.WriteLine("org list search Complete");