using Gate.ExpressionBuilder;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Fast.Framework
{
public static class PredicateBuilder
{
/// <summary>
/// 创建lambda表达式:p=>true
/// </summary>
/// <typeparam name="T">对象名称(类名)</typeparam>
/// <returns></returns>
public static Expression<Func<T, bool>> True<T>()
{
return p => true;
}
/// <summary>
/// 创建lambda表达式:p=>false
/// </summary>
/// <typeparam name="T">对象名称(类名)</typeparam>
/// <returns></returns>
public static Expression<Func<T, bool>> False<T>()
{
return p => false;
}
/// <summary>
/// 以 Expression.AndAlso 组合两个Expression表达式
/// </summary>
/// <typeparam name="T">表达式的主实体类型</typeparam>
/// <param name="first">第一个Expression表达式</param>
/// <param name="second">要组合的Expression表达式</param>
/// <returns>组合后的表达式</returns>
public static Expression<Func<T, bool>> And<T>(Expression<Func<T, bool>> first,
Expression<Func<T, bool>> second)
{
return first.Compose(second, Expression.AndAlso);
}
/// <summary>
/// 以 Expression.OrElse 组合两个Expression表达式
/// </summary>
/// <typeparam name="T">表达式的主实体类型</typeparam>
/// <param name="first">第一个Expression表达式</param>
/// <param name="second">要组合的Expression表达式</param>
/// <returns>组合后的表达式</returns>
public static Expression<Func<T, bool>> Or<T>(Expression<Func<T, bool>> first,
Expression<Func<T, bool>> second)
{
return first.Compose(second, Expression.OrElse);
}
#region 表达式组合辅助方法
/// <summary>
/// 以特定的条件运行组合两个Expression表达式
/// </summary>
/// <typeparam name="T">表达式的主实体类型</typeparam>
/// <param name="first">第一个Expression表达式</param>
/// <param name="second">要组合的Expression表达式</param>
/// <param name="merge">组合条件运算方式</param>
/// <returns>组合后的表达式</returns>
private static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second,
Func<Expression, Expression, Expression> merge)
{
var map =
first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
}
#endregion
/// <summary>
/// 创建lambda表达式:p=>p.propertyName
/// </summary>
/// <typeparam name="T">对象名称(类名)</typeparam>
/// <typeparam name="TKey">参数类型</typeparam>
/// <param name="propertyName">字段名称(数据库中字段名称)</param>
/// <returns></returns>
public static Expression<Func<T, TKey>> GetOrderExpression<T, TKey>(string propertyName)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "p");
return Expression.Lambda<Func<T, TKey>>(Expression.Property(parameter, propertyName), parameter);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName == propertyValue
/// </summary>
/// <typeparam name="T">对象名称(类名)</typeparam>
/// <typeparam name="S">参数类型</typeparam>
/// <param name="propertyName">字段名称(数据库中字段名称)</param>
/// <param name="propertyValue">数据值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateEqual<T, S>(string propertyName, S propertyValue)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "p");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue, typeof(S));//创建常数
return Expression.Lambda<Func<T, bool>>(Expression.Equal(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName != propertyValue
/// </summary>
/// <typeparam name="T">对象名称(类名)</typeparam>
/// <typeparam name="S">参数类型</typeparam>
/// <param name="propertyName">字段名称(数据库中字段名称)</param>
/// <param name="propertyValue">数据值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateNotEqual<T, S>(string propertyName, S propertyValue)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "p");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue, typeof(S));//创建常数
return Expression.Lambda<Func<T, bool>>(Expression.NotEqual(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName > propertyValue
/// </summary>
/// <typeparam name="T">对象名称(类名)</typeparam>
/// <typeparam name="S">参数类型</typeparam>
/// <param name="propertyName">字段名称(数据库中字段名称)</param>
/// <param name="propertyValue">数据值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateGreaterThan<T, S>(string propertyName, S propertyValue)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "p");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue, typeof(S));//创建常数
return Expression.Lambda<Func<T, bool>>(Expression.GreaterThan(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:p=> propertyValue > p.propertyName
/// </summary>
/// <typeparam name="T">对象名称(类名)</typeparam>
/// <typeparam name="S">参数类型</typeparam>
/// <param name="propertyName">字段名称(数据库中字段名称)</param>
/// <param name="propertyValue">数据值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateLessThan<T, S>(string propertyName, S propertyValue)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "p");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue, typeof(S));//创建常数
return Expression.Lambda<Func<T, bool>>(Expression.LessThan(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName >= propertyValue
/// </summary>
/// <typeparam name="T">对象名称(类名)</typeparam>
/// <typeparam name="S">参数类型</typeparam>
/// <param name="propertyName">字段名称(数据库中字段名称)</param>
/// <param name="propertyValue">数据值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateGreaterThanOrEqual<T, S>(string propertyName, S propertyValue)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "p");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue, typeof(S));//创建常数
return Expression.Lambda<Func<T, bool>>(Expression.GreaterThanOrEqual(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:p=>propertyValue >= p.propertyName
/// </summary>
/// <typeparam name="T">对象名称(类名)</typeparam>
/// <typeparam name="S">参数类型</typeparam>
/// <param name="propertyName">字段名称(数据库中字段名称)</param>
/// <param name="propertyValue">数据值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateLessThanOrEqual<T, S>(string propertyName, S propertyValue)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "p");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue, typeof(S));//创建常数
return Expression.Lambda<Func<T, bool>>(Expression.LessThanOrEqual(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName.Contains(propertyValue)
/// </summary>
/// <typeparam name="T">对象名称(类名)</typeparam>
/// <param name="propertyName">字段名称(数据库中字段名称)</param>
/// <param name="propertyValue">数据值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateContains<T>(string propertyName, string propertyValue)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "p");
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
ConstantExpression constant = Expression.Constant(propertyValue, typeof(string));
return Expression.Lambda<Func<T, bool>>(Expression.Call(member, method, constant), parameter);
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="propertyName"></param>
/// <param name="propVals"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateIn<T>(string propertyName, List<string> propVals)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "p");
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
MethodInfo method = typeof(List<string>).GetMethod("Contains", new[] { typeof(string) });
ConstantExpression constant = Expression.Constant(propVals, typeof(List<string>));
return Expression.Lambda<Func<T, bool>>(Expression.Call(constant, method, member), parameter);
//return Expression.Lambda<Func<T, bool>>(Expression.Call(member, method, constant), parameter);
}
public static Expression<Func<T, bool>> CreateIn<T>(string propertyName, string[] propVals)
{
List<string> pVals = propVals.ToList();
return CreateIn<T>(propertyName, pVals);
}
public static Expression<Func<T, bool>> CreateIn<T>(string propertyName, List<int> propVals)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "p");
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
MethodInfo method = typeof(List<int>).GetMethod("Contains", new[] { typeof(int) });
ConstantExpression constant = Expression.Constant(propVals, typeof(List<int>));
return Expression.Lambda<Func<T, bool>>(Expression.Call(constant, method, member), parameter);
//return Expression.Lambda<Func<T, bool>>(Expression.Call(member, method, constant), parameter);
}
public static Expression<Func<T, bool>> CreateIn<T>(string propertyName, int[] propVals)
{
List<int> pVals = propVals.ToList();
return CreateIn<T>(propertyName, pVals);
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="propertyName"></param>
/// <param name="propVals"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateBetween<T>(string propertyName, DateTime[] propVals)
{
if (propVals.Length < 2)
{
throw new ArgumentException("CreateBetween[ parameter propVals need two values]");
}
var lowBound = CreateGreaterThanOrEqual<T,DateTime>(propertyName, propVals[0]);
var upBound = CreateLessThanOrEqual<T, DateTime>(propertyName, propVals[1]);
return And<T>(lowBound, upBound);
}
/// <summary>
/// 创建lambda表达式:!(p=>p.propertyName.Contains(propertyValue))
/// </summary>
/// <typeparam name="T">对象名称(类名)</typeparam>
/// <param name="propertyName">字段名称(数据库中字段名称)</param>
/// <param name="propertyValue">数据值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateNotContains<T>(string propertyName, string propertyValue)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "p");
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
ConstantExpression constant = Expression.Constant(propertyValue, typeof(string));
return Expression.Lambda<Func<T, bool>>(Expression.Not(Expression.Call(member, method, constant)), parameter);
}
}
}