• 表达式树在LINQ动态查询


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

    [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查询结束!花了上班时间一上午,还是相当值得的,不过被项目经理知道了得哭死!

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

  • 相关阅读:
    进程同步&&进程互斥
    CHAP4 字符串和格式化输入输出
    记录学习到的内容
    数据链路层 差错控制
    二叉树的顺序存储
    Java复习笔记
    Stream流
    函数式接口
    网络编程
    接口,多态,抽象类总结
  • 原文地址:https://www.cnblogs.com/sjqq/p/8550305.html
Copyright © 2020-2023  润新知