123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- using System;
- using System.Collections.ObjectModel;
- using System.Linq.Expressions;
- using System.Reflection;
- namespace wispro.sp.utility
- {
- public class Query
- {
- public enum Operators
- {
- None = 0,
- Equal = 1,
- GreaterThan = 2,
- GreaterThanOrEqual = 3,
- LessThan = 4,
- LessThanOrEqual = 5,
- Contains = 6,
- StartWith = 7,
- EndWidth = 8,
- Range = 9
- }
- public enum Condition
- {
- OrElse = 1,
- AndAlso = 2
- }
- public string Name { get; set; }
- public Operators Operator { get; set; }
- public object Value { get; set; }
- public object ValueMin { get; set; }
- public object ValueMax { get; set; }
- public class QueryCollection : Collection<Query>
- {
- public Expression<Func<T, bool>> AsExpression<T>(Query.Condition? condition = Query.Condition.OrElse) where T : class
- {
- Type targetType = typeof(T);
- TypeInfo typeInfo = targetType.GetTypeInfo();
- var parameter = Expression.Parameter(targetType, "m");
- Expression expression = null;
- Func<Expression, Expression, Expression> Append = (exp1, exp2) =>
- {
- if (exp1 == null)
- {
- return exp2;
- }
- return (condition ?? Query.Condition.OrElse) == Query.Condition.OrElse ? Expression.OrElse(exp1, exp2) : Expression.AndAlso(exp1, exp2);
- };
- foreach (var item in this)
- {
- var property = typeInfo.GetProperty(item.Name);
- if (property == null ||
- !property.CanRead ||
- (item.Operator != Query.Operators.Range && item.Value == null) ||
- (item.Operator == Query.Operators.Range && item.ValueMin == null && item.ValueMax == null))
- {
- continue;
- }
- Type realType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
- if (item.Value != null)
- {
- item.Value = Convert.ChangeType(item.Value, realType);
- }
- Expression<Func<object>> valueLamba = () => item.Value;
- switch (item.Operator)
- {
- case Query.Operators.Equal:
- {
- expression = Append(expression, Expression.Equal(Expression.Property(parameter, item.Name),
- Expression.Convert(valueLamba.Body, property.PropertyType)));
- break;
- }
- case Query.Operators.GreaterThan:
- {
- expression = Append(expression, Expression.GreaterThan(Expression.Property(parameter, item.Name),
- Expression.Convert(valueLamba.Body, property.PropertyType)));
- break;
- }
- case Query.Operators.GreaterThanOrEqual:
- {
- expression = Append(expression, Expression.GreaterThanOrEqual(Expression.Property(parameter, item.Name),
- Expression.Convert(valueLamba.Body, property.PropertyType)));
- break;
- }
- case Query.Operators.LessThan:
- {
- expression = Append(expression, Expression.LessThan(Expression.Property(parameter, item.Name),
- Expression.Convert(valueLamba.Body, property.PropertyType)));
- break;
- }
- case Query.Operators.LessThanOrEqual:
- {
- expression = Append(expression, Expression.LessThanOrEqual(Expression.Property(parameter, item.Name),
- Expression.Convert(valueLamba.Body, property.PropertyType)));
- break;
- }
- case Query.Operators.Contains:
- {
- var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, Expression.Property(parameter, item.Name)));
- var contains = Expression.Call(Expression.Property(parameter, item.Name), "Contains", null,
- Expression.Convert(valueLamba.Body, property.PropertyType));
- expression = Append(expression, Expression.AndAlso(nullCheck, contains));
- break;
- }
- case Query.Operators.StartWith:
- {
- var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, Expression.Property(parameter, item.Name)));
- var startsWith = Expression.Call(Expression.Property(parameter, item.Name), "StartsWith", null,
- Expression.Convert(valueLamba.Body, property.PropertyType));
- expression = Append(expression, Expression.AndAlso(nullCheck, startsWith));
- break;
- }
- case Query.Operators.EndWidth:
- {
- var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, Expression.Property(parameter, item.Name)));
- var endsWith = Expression.Call(Expression.Property(parameter, item.Name), "EndsWith", null,
- Expression.Convert(valueLamba.Body, property.PropertyType));
- expression = Append(expression, Expression.AndAlso(nullCheck, endsWith));
- break;
- }
- case Query.Operators.Range:
- {
- Expression minExp = null, maxExp = null;
- if (item.ValueMin != null)
- {
- var minValue = Convert.ChangeType(item.ValueMin, realType);
- Expression<Func<object>> minValueLamda = () => minValue;
- minExp = Expression.GreaterThanOrEqual(Expression.Property(parameter, item.Name), Expression.Convert(minValueLamda.Body, property.PropertyType));
- }
- if (item.ValueMax != null)
- {
- var maxValue = Convert.ChangeType(item.ValueMax, realType);
- Expression<Func<object>> maxValueLamda = () => maxValue;
- maxExp = Expression.LessThanOrEqual(Expression.Property(parameter, item.Name), Expression.Convert(maxValueLamda.Body, property.PropertyType));
- }
- if (minExp != null && maxExp != null)
- {
- expression = Append(expression, Expression.AndAlso(minExp, maxExp));
- }
- else if (minExp != null)
- {
- expression = Append(expression, minExp);
- }
- else if (maxExp != null)
- {
- expression = Append(expression, maxExp);
- }
- break;
- }
- }
- }
- if (expression == null)
- {
- return null;
- }
- return ((Expression<Func<T, bool>>)Expression.Lambda(expression, parameter));
- }
- }
- }
- }
|