动态构建表达式树,最佳实践版,很实用!
- public class FilterCollection : Collection<IList<Filter>>
- {
- public FilterCollection()
- : base()
- { }
- }
- public class Filter
- {
- public string PropertyName { get; set; }
- public Op Operation { get; set; }
- public object Value { get; set; }
- }
- public enum Op
- {
- Equals,
- GreaterThan,
- LessThan,
- GreaterThanOrEqual,
- LessThanOrEqual,
- Contains,
- StartsWith,
- EndsWith
- }
通过上面的类可以动态构建复杂的查询条件,下面具体调用的类哦
- using Infrastructure.Model;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Reflection;
- using System.Text;
- using System.Threading.Tasks;
- namespace Infrastructure.Operation
- {
- public static class LambdaExpressionBuilder
- {
- private static MethodInfo containsMethod = typeof(string).GetMethod("Contains");
- private static MethodInfo startsWithMethod =
- typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
- private static MethodInfo endsWithMethod =
- typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) });
- private static Expression GetExpression(ParameterExpression param, Filter filter)
- {
- MemberExpression member = Expression.Property(param, filter.PropertyName);
- Expression handledMember = member;
- ConstantExpression constant = Expression.Constant(filter.Value);
- if (member.Member.MemberType == MemberTypes.Property)
- {
- Type propertyType = ((PropertyInfo)member.Member).PropertyType;
- if (propertyType == typeof(string))
- {
- handledMember = Expression.Call(member, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
- }
- if (propertyType == typeof(DateTime?))
- {
- handledMember = Expression.Property(member, typeof(DateTime?).GetProperty("Value"));
- }
- }
- switch (filter.Operation)
- {
- case Op.Equals:
- return Expression.Equal(handledMember, constant);
- case Op.GreaterThan:
- return Expression.GreaterThan(handledMember, constant);
- case Op.GreaterThanOrEqual:
- return Expression.GreaterThanOrEqual(handledMember, constant);
- case Op.LessThan:
- return Expression.LessThan(handledMember, constant);
- case Op.LessThanOrEqual:
- return Expression.LessThanOrEqual(handledMember, constant);
- case Op.Contains:
- return Expression.Call(handledMember, containsMethod, constant);
- case Op.StartsWith:
- return Expression.Call(handledMember, startsWithMethod, constant);
- case Op.EndsWith:
- return Expression.Call(handledMember, endsWithMethod, constant);
- }
- return null;
- }
- private static BinaryExpression GetORExpression(ParameterExpression param, Filter filter1, Filter filter2)
- {
- Expression bin1 = GetExpression(param, filter1);
- Expression bin2 = GetExpression(param, filter2);
- return Expression.Or(bin1, bin2);
- }
- private static Expression GetExpression(ParameterExpression param, IList<Filter> orFilters)
- {
- if (orFilters.Count == 0)
- return null;
- Expression exp = null;
- if (orFilters.Count == 1)
- {
- exp = GetExpression(param, orFilters[0]);
- }
- else if (orFilters.Count == 2)
- {
- exp = GetORExpression(param, orFilters[0], orFilters[1]);
- }
- else
- {
- while (orFilters.Count > 0)
- {
- var f1 = orFilters[0];
- var f2 = orFilters[1];
- if (exp == null)
- {
- exp = GetORExpression(param, orFilters[0], orFilters[1]);
- }
- else
- {
- exp = Expression.Or(exp, GetORExpression(param, orFilters[0], orFilters[1]));
- }
- orFilters.Remove(f1);
- orFilters.Remove(f2);
- if (orFilters.Count == 1)
- {
- exp = Expression.Or(exp, GetExpression(param, orFilters[0]));
- orFilters.RemoveAt(0);
- }
- }
- }
- return exp;
- }
- public static Expression<Func<T, bool>> GetExpression<T>(FilterCollection filters)
- {
- if (filters == null || filters.Count == 0)
- return null;
- ParameterExpression param = Expression.Parameter(typeof(T), "t");
- Expression exp = null;
- if (filters.Count == 1)
- {
- exp = GetExpression(param, filters[0]);
- }
- else if (filters.Count == 2)
- {
- exp = Expression.AndAlso(GetExpression(param, filters[0]), GetExpression(param, filters[1]));
- }
- else
- {
- while (filters.Count > 0)
- {
- var f1 = filters[0];
- var f2 = filters[1];
- var f1Andf2 = Expression.AndAlso(GetExpression(param, filters[0]), GetExpression(param, filters[1]));
- if (exp == null)
- {
- exp = f1Andf2;
- }
- else
- {
- exp = Expression.AndAlso(exp, f1Andf2);
- }
- filters.Remove(f1);
- filters.Remove(f2);
- if (filters.Count == 1)
- {
- exp = Expression.AndAlso(exp, GetExpression(param, filters[0]));
- filters.RemoveAt(0);
- }
- }
- }
- return Expression.Lambda<Func<T, bool>>(exp, param);
- }
- }
- }
再来一个OrderBy动态构建
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Reflection;
- using System.Text;
- namespace Jurassic.Sooil.Com
- {
- public static class OrderExpression
- {
- public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property)
- {
- return ApplyOrder<T>(source, property, "OrderBy");
- }
- public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string property)
- {
- return ApplyOrder<T>(source, property, "OrderByDescending");
- }
- public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string property)
- {
- return ApplyOrder<T>(source, property, "ThenBy");
- }
- public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string property)
- {
- return ApplyOrder<T>(source, property, "ThenByDescending");
- }
- static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, string methodName)
- {
- string[] props = property.Split('.');
- Type type = typeof(T);
- ParameterExpression arg = Expression.Parameter(type, "x");
- Expression expr = arg;
- foreach (string prop in props)
- {
- // use reflection (not ComponentModel) to mirror LINQ
- PropertyInfo pi = type.GetProperty(prop);
- expr = Expression.Property(expr, pi);
- type = pi.PropertyType;
- }
- Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
- LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);
- object result = typeof(Queryable).GetMethods().Single(
- method => method.Name == methodName
- && method.IsGenericMethodDefinition
- && method.GetGenericArguments().Length == 2
- && method.GetParameters().Length == 2)
- .MakeGenericMethod(typeof(T), type)
- .Invoke(null, new object[] { source, lambda });
- return (IOrderedQueryable<T>)result;
- }
- }
- }
至此动态构建LINQ查询结束!花了上班时间一上午,还是相当值得的,不过被项目经理知道了得哭死!
不管如何,学到手的才是自己的!