一般如果逻辑比较简单,只是存在有的情况多一个查询条件,有的情况不需要添加该查询条件

简单方式这样操作就可以了

 

[csharp] view plain copy
 
  1. public IQueryable<FileImport> DynamicChainedSyntax  
  2.         (IQueryable<FileImport> files, bool pastOnly)  
  3. {  
  4.     var query = files.Where(file => file.ImportDate >  
  5.                 DateTime.Now.AddDays(-7));  
  6.     if (pastOnly)  
  7.         query = query.Where(file => file.ImportDate <  
  8.                 DateTime.Today);  
  9.     return query;  
  10. }  


这里的多个where条件是AND关系,如果是OR的关系,可将多次查询的结果进行union

 

 

当然大多数的时候,我们是希望能够动态构建查询条件的,你可以针对任何字段进行任何操作符形式的查询,不同查询条件之间的关系也是可以动态定义的。

这时候表达式树就派上用场了,关于表达式树的基础知识已经在上一篇中提到了。

这里主要说如何构建linq中Where查询条件,其实只是熟悉表达式树的其他提供的方法,非常简单。

 

[csharp] view plain copy
 
  1. public Func<TSource, bool> SimpleComparison<TSource>              
  2.             string property, object value)  
  3. {  
  4.     var type = typeof (TSource);  
  5.     var pe = Expression.Parameter(type, "p");  
  6.     var propertyReference = Expression.Property(pe, property);  
  7.     var constantReference = Expression.Constant(value);  
  8.     return Expression.Lambda<Func<TSource, bool>>  
  9.         (Expression.Equal(propertyReference, constantReference),  
  10.         new[] { pe }).Compile();  
  11. }  

 

呵呵,话到这里,看看我的小DEMO

 

[csharp] view plain copy
 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Linq.Expressions;  
  5. using System.Text;  
  6. using System.Threading.Tasks;  
  7.   
  8. namespace ConsoleApplication1  
  9. {  
  10.     class Program  
  11.     {  
  12.         static void Main(string[] args)  
  13.         {  
  14.             //(a,b)=>(a+b)  
  15.             //参数的构建  (定义参数的名字和参数的类型)  
  16.             ParameterExpression exp1 = Expression.Parameter(typeof(int), "a");  
  17.             ParameterExpression exp2 = Expression.Parameter(typeof(int), "b");  
  18.             //表达式主体的构建   
  19.             BinaryExpression exp = Expression.Add(exp1, exp2);  
  20.             //表达式树的构建(如下定义,表达式的类型为Lambda   
  21.             //lambda表达式的类型为Func<int, int, int>)  
  22.             var lambda = Expression.Lambda<Func<int, int, int>>(exp, exp1, exp2);  
  23.   
  24.             //p=>p.Name 可以动态构建OrderBy  
  25.             ParameterExpression exp3 = Expression.Parameter(typeof(Person), "p");  
  26.             var property = Expression.Property(exp3, "Name");  
  27.             var lambda2 = Expression.Lambda<Func<Person, string>>(property, exp3);  
  28.   
  29.             //p=>p.Name == "daisy"   
  30.             List<Person> persons = new List<Person>()   
  31.             { new Person(){ Name = "daisy", age = 10 },  
  32.               new Person(){ Name = "daisy", age = 12 },   
  33.               new Person(){Name="dom", age=12},  
  34.               new Person(){Name="caren", age=10}};  
  35.             var compareExp = simpleCompare<Person>("Name", "daisy");  
  36.             var daisys = persons.Where(compareExp).ToList();  
  37.             foreach (var item in daisys)  
  38.             {  
  39.                 Console.WriteLine("Name:  "+item.Name+"    Age:  "+item.age);  
  40.             }  
  41.             Console.ReadKey();  
  42.         }  
  43.         public static Func<TSource, bool> simpleCompare<TSource>(string property, object value)  
  44.         {  
  45.             var type = typeof(TSource);  
  46.             var pe = Expression.Parameter(type, "p");  
  47.             var propertyReference = Expression.Property(pe, property);  
  48.             var constantReference = Expression.Constant(value);  
  49.   
  50.             //compile 是表达式的一个接口,生成该lambda表达式树对的委托  
  51.             return Expression.Lambda<Func<TSource, bool>>(Expression.Equal(propertyReference, constantReference), pe).Compile();  
  52.         }  
  53.   
  54.     }  
  55.     public class Person  
  56.     {  
  57.         public string Name { get; set; }  
  58.         public int age { get; set; }  
  59.     }  
  60. }  


再来看看查询结果:

 

 

嗯,理解起来还是非常简单的,就是构建表达式树,返回我们需要的委托类型!

 

接下来猛料哦

动态构建表达式树,最佳实践版,很实用!

 

[csharp] view plain copy
 
  1. public class FilterCollection : Collection<IList<Filter>>  
  2.    {  
  3.        public FilterCollection()  
  4.            : base()  
  5.        { }  
  6.    }  
  7.   
  8.    public class Filter  
  9.    {  
  10.        public string PropertyName { get; set; }  
  11.        public Op Operation { get; set; }  
  12.        public object Value { get; set; }  
  13.    }  
  14.   
  15.    public enum Op  
  16.    {  
  17.        Equals,  
  18.        GreaterThan,  
  19.        LessThan,  
  20.        GreaterThanOrEqual,  
  21.        LessThanOrEqual,  
  22.        Contains,  
  23.        StartsWith,  
  24.        EndsWith  
  25.    }  


通过上面的类可以动态构建复杂的查询条件,下面具体调用的类哦

 

 

[csharp] view plain copy
 
  1. using Infrastructure.Model;  
  2. using System;  
  3. using System.Collections.Generic;  
  4. using System.Linq;  
  5. using System.Linq.Expressions;  
  6. using System.Reflection;  
  7. using System.Text;  
  8. using System.Threading.Tasks;  
  9.   
  10. namespace Infrastructure.Operation  
  11. {  
  12.     public static class LambdaExpressionBuilder  
  13.     {  
  14.         private static MethodInfo containsMethod = typeof(string).GetMethod("Contains");  
  15.         private static MethodInfo startsWithMethod =  
  16.                                 typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });  
  17.         private static MethodInfo endsWithMethod =  
  18.                                 typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) });  
  19.         private static Expression GetExpression(ParameterExpression param, Filter filter)  
  20.         {  
  21.             MemberExpression member = Expression.Property(param, filter.PropertyName);  
  22.             Expression handledMember = member;  
  23.             ConstantExpression constant = Expression.Constant(filter.Value);  
  24.   
  25.             if (member.Member.MemberType == MemberTypes.Property)  
  26.             {  
  27.                 Type propertyType = ((PropertyInfo)member.Member).PropertyType;  
  28.                 if (propertyType == typeof(string))  
  29.                 {  
  30.                     handledMember = Expression.Call(member, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));  
  31.                 }  
  32.                 if (propertyType == typeof(DateTime?))  
  33.                 {  
  34.                     handledMember = Expression.Property(member, typeof(DateTime?).GetProperty("Value"));  
  35.                 }  
  36.             }  
  37.   
  38.             switch (filter.Operation)  
  39.             {  
  40.                 case Op.Equals:  
  41.                     return Expression.Equal(handledMember, constant);  
  42.                 case Op.GreaterThan:  
  43.                     return Expression.GreaterThan(handledMember, constant);  
  44.                 case Op.GreaterThanOrEqual:  
  45.                     return Expression.GreaterThanOrEqual(handledMember, constant);  
  46.                 case Op.LessThan:  
  47.                     return Expression.LessThan(handledMember, constant);  
  48.                 case Op.LessThanOrEqual:  
  49.                     return Expression.LessThanOrEqual(handledMember, constant);  
  50.                 case Op.Contains:  
  51.                     return Expression.Call(handledMember, containsMethod, constant);  
  52.                 case Op.StartsWith:  
  53.                     return Expression.Call(handledMember, startsWithMethod, constant);  
  54.                 case Op.EndsWith:  
  55.                     return Expression.Call(handledMember, endsWithMethod, constant);  
  56.             }  
  57.   
  58.             return null;  
  59.         }  
  60.         private static BinaryExpression GetORExpression(ParameterExpression param, Filter filter1, Filter filter2)  
  61.         {  
  62.             Expression bin1 = GetExpression(param, filter1);  
  63.             Expression bin2 = GetExpression(param, filter2);  
  64.   
  65.             return Expression.Or(bin1, bin2);  
  66.         }  
  67.   
  68.         private static Expression GetExpression(ParameterExpression param, IList<Filter> orFilters)  
  69.         {  
  70.             if (orFilters.Count == 0)  
  71.                 return null;  
  72.   
  73.             Expression exp = null;  
  74.   
  75.             if (orFilters.Count == 1)  
  76.             {  
  77.                 exp = GetExpression(param, orFilters[0]);  
  78.             }  
  79.             else if (orFilters.Count == 2)  
  80.             {  
  81.                 exp = GetORExpression(param, orFilters[0], orFilters[1]);  
  82.             }  
  83.             else  
  84.             {  
  85.                 while (orFilters.Count > 0)  
  86.                 {  
  87.                     var f1 = orFilters[0];  
  88.                     var f2 = orFilters[1];  
  89.   
  90.                     if (exp == null)  
  91.                     {  
  92.                         exp = GetORExpression(param, orFilters[0], orFilters[1]);  
  93.                     }  
  94.                     else  
  95.                     {  
  96.                         exp = Expression.Or(exp, GetORExpression(param, orFilters[0], orFilters[1]));  
  97.                     }  
  98.                     orFilters.Remove(f1);  
  99.                     orFilters.Remove(f2);  
  100.   
  101.                     if (orFilters.Count == 1)  
  102.                     {  
  103.                         exp = Expression.Or(exp, GetExpression(param, orFilters[0]));  
  104.                         orFilters.RemoveAt(0);  
  105.                     }  
  106.                 }  
  107.             }  
  108.   
  109.             return exp;  
  110.         }  
  111.   
  112.         public static Expression<Func<T, bool>> GetExpression<T>(FilterCollection filters)  
  113.         {  
  114.             if (filters == null || filters.Count == 0)  
  115.                 return null;  
  116.   
  117.             ParameterExpression param = Expression.Parameter(typeof(T), "t");  
  118.             Expression exp = null;  
  119.   
  120.             if (filters.Count == 1)  
  121.             {  
  122.                 exp = GetExpression(param, filters[0]);  
  123.             }  
  124.             else if (filters.Count == 2)  
  125.             {  
  126.                 exp = Expression.AndAlso(GetExpression(param, filters[0]), GetExpression(param, filters[1]));  
  127.             }  
  128.   
  129.             else  
  130.             {  
  131.                 while (filters.Count > 0)  
  132.                 {  
  133.                     var f1 = filters[0];  
  134.                     var f2 = filters[1];  
  135.                     var f1Andf2 = Expression.AndAlso(GetExpression(param, filters[0]), GetExpression(param, filters[1]));  
  136.                     if (exp == null)  
  137.                     {  
  138.                         exp = f1Andf2;  
  139.                     }  
  140.                     else  
  141.                     {  
  142.                         exp = Expression.AndAlso(exp, f1Andf2);  
  143.                     }  
  144.   
  145.                     filters.Remove(f1);  
  146.                     filters.Remove(f2);  
  147.   
  148.                     if (filters.Count == 1)  
  149.                     {  
  150.                         exp = Expression.AndAlso(exp, GetExpression(param, filters[0]));  
  151.                         filters.RemoveAt(0);  
  152.                     }  
  153.                 }  
  154.             }  
  155.   
  156.             return Expression.Lambda<Func<T, bool>>(exp, param);  
  157.         }  
  158.     }  
  159. }  


再来一个OrderBy动态构建

 

 

[csharp] view plain copy
 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Linq.Expressions;  
  5. using System.Reflection;  
  6. using System.Text;  
  7.   
  8. namespace Jurassic.Sooil.Com  
  9. {  
  10.     public static class OrderExpression  
  11.     {  
  12.         public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property)  
  13.         {  
  14.             return ApplyOrder<T>(source, property, "OrderBy");  
  15.         }  
  16.         public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string property)  
  17.         {  
  18.             return ApplyOrder<T>(source, property, "OrderByDescending");  
  19.         }  
  20.         public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string property)  
  21.         {  
  22.             return ApplyOrder<T>(source, property, "ThenBy");  
  23.         }  
  24.         public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string property)  
  25.         {  
  26.             return ApplyOrder<T>(source, property, "ThenByDescending");  
  27.         }  
  28.         static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, string methodName)  
  29.         {  
  30.             string[] props = property.Split('.');  
  31.             Type type = typeof(T);  
  32.             ParameterExpression arg = Expression.Parameter(type, "x");  
  33.             Expression expr = arg;  
  34.             foreach (string prop in props)  
  35.             {  
  36.                 // use reflection (not ComponentModel) to mirror LINQ  
  37.                 PropertyInfo pi = type.GetProperty(prop);  
  38.                 expr = Expression.Property(expr, pi);  
  39.                 type = pi.PropertyType;  
  40.             }  
  41.             Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);  
  42.             LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);  
  43.   
  44.             object result = typeof(Queryable).GetMethods().Single(  
  45.                     method => method.Name == methodName  
  46.                             && method.IsGenericMethodDefinition  
  47.                             && method.GetGenericArguments().Length == 2  
  48.                             && method.GetParameters().Length == 2)  
  49.                     .MakeGenericMethod(typeof(T), type)  
  50.                     .Invoke(null, new object[] { source, lambda });  
  51.             return (IOrderedQueryable<T>)result;  
  52.         }   
  53.     }  
  54. }  


至此动态构建LINQ查询结束!花了上班时间一上午,还是相当值得的,不过被项目经理知道了得哭死!

 

不管如何,学到手的才是自己的!