/// <summary>
/// 根據T 轉換lambda 表達式
/// </summary>
/// <typeparam name="TRequest"></typeparam>
/// <typeparam name="T"></typeparam>
/// <param name="request"></param>
public static Expression<Func<T, bool>> GetLambdaByRequest<TRequest, T>(TRequest request) where T : class
{
Expression<Func<T, bool>> where = ex => true;
foreach (PropertyInfo info in typeof(TRequest).GetProperties())
{
object value = info.GetValue(request, null);
if (info.Name != "CurrentPage" && info.Name != "PageSize" && value != null && value.ToString() != "")
{
if (info.Name == "Title")
{
where = where.And(LambdaUtil<T>.In(info.Name, value.ToString().Split(",")));
}
else
{
where = where.And(LambdaUtil<T>.Equal(info.Name, info.GetValue(request, null)));
}
}
}
return where;
}
/// <summary>
/// LambdaHelper 擴展
/// </summary>
public static class LambdaHelper
{
/// <summary>
/// Lambda表達式拼接
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="first"></param>
/// <param name="second"></param>
/// <param name="merge"></param>
/// <returns></returns>
public static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
{
// build parameter map (from parameters of second to parameters of first)
var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
// replace parameters in the second lambda expression with parameters from the first
var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
// apply composition of lambda expression bodies to parameters from the first expression
return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
}
/// <summary>
/// and擴展
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="first"></param>
/// <param name="second"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose(second, Expression.And);
}
/// <summary>
/// or擴展
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="first"></param>
/// <param name="second"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose(second, Expression.Or);
}
}
/// <summary>
///
/// </summary>
public class ParameterRebinder : ExpressionVisitor
{
private readonly Dictionary<ParameterExpression, ParameterExpression> map;
/// <summary>
///
/// </summary>
/// <param name="map"></param>
public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
{
this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
}
/// <summary>
///
/// </summary>
/// <param name="map"></param>
/// <param name="exp"></param>
/// <returns></returns>
public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
{
return new ParameterRebinder(map).Visit(exp);
}
/// <summary>
///
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
protected override Expression VisitParameter(ParameterExpression p)
{
ParameterExpression replacement;
if (map.TryGetValue(p, out replacement))
{
p = replacement;
}
return base.VisitParameter(p);
}
}
/// <summary>
/// Lambda 表達式 基礎類
/// </summary>
/// <typeparam name="T"></typeparam>
public static class LambdaUtil<T>
{
/// <summary>
/// lambda表達式:t=>true
/// </summary>
/// <returns></returns>
public static Expression<Func<T, bool>> True()
{
return t => true;
}
/// <summary>
/// lambda表達式:t=>false
/// </summary>
/// <returns></returns>
public static Expression<Func<T, bool>> False()
{
return t => false;
}
/// <summary>
/// lambda表達式:t=>t.propName
/// 多用於order排序
/// </summary>
/// <typeparam name="T">參數類型</typeparam>
/// <typeparam name="TKey">返回類型</typeparam>
/// <param name="propName">屬性名</param>
/// <returns></returns>
private static Expression<Func<T, TKey>> Order<TKey>(string propName)
{
// 創建節點參數t
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
// 創建一個屬性
MemberExpression property = Expression.Property(parameter, propName);
// 生成lambda表達式
return Expression.Lambda<Func<T, TKey>>(property, parameter);
}
/// <summary>
/// lambda表達式:t=>t.propName==propValue
/// 多用於where條件
/// </summary>
/// <typeparam name="T">參數類型</typeparam>
/// <param name="propName">屬性名稱</param>
/// <param name="propValue">屬性值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> Equal(string propName, object propValue)
{
// 創建節點參數t
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
// 創建一個成員(字段/屬性)
MemberExpression member = Expression.PropertyOrField(parameter, propName);
// 創建一個常數
ConstantExpression constant = Expression.Constant(propValue);
// 創建一個相等比較Expression
BinaryExpression binary = Expression.Equal(member, constant);
// 生成lambda表達式
return Expression.Lambda<Func<T, bool>>(binary, parameter);
}
/// <summary>
/// lambda表達式:t=>t.propName!=propValue
/// 多用於where條件
/// </summary>
/// <typeparam name="T">參數類型</typeparam>
/// <param name="propName">屬性名稱</param>
/// <param name="propValue">屬性值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> NotEqual(string propName, string propValue)
{
// 創建節點參數t
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
// 創建一個成員(字段/屬性)
MemberExpression member = Expression.PropertyOrField(parameter, propName);
// 創建一個常數
ConstantExpression constant = Expression.Constant(propValue);
// 創建一個不相等比較Expression
BinaryExpression binary = Expression.NotEqual(member, constant);
// 生成lambda表達式
return Expression.Lambda<Func<T, bool>>(binary, parameter);
}
/// <summary>
/// lambda表達式:t=>t.propName<propValue
/// 多用於where條件
/// </summary>
/// <typeparam name="T">參數類型</typeparam>
/// <param name="propName">屬性名稱</param>
/// <param name="propValue">屬性值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> LessThan(string propName, string propValue)
{
// 創建節點參數t
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
// 創建一個成員(字段/屬性)
MemberExpression member = Expression.PropertyOrField(parameter, propName);
// 創建一個常數
ConstantExpression constant = Expression.Constant(propValue);
// 創建一個不相等比較Expression
BinaryExpression binary = Expression.LessThan(member, constant);
// 生成lambda表達式
return Expression.Lambda<Func<T, bool>>(binary, parameter);
}
/// <summary>
/// lambda表達式:t=>t.propName<=propValue
/// 多用於where條件
/// </summary>
/// <typeparam name="T">參數類型</typeparam>
/// <param name="propName">屬性名稱</param>
/// <param name="propValue">屬性值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> LessThanOrEqual(string propName, string propValue)
{
// 創建節點參數t
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
// 創建一個成員(字段/屬性)
MemberExpression member = Expression.PropertyOrField(parameter, propName);
// 創建一個常數
ConstantExpression constant = Expression.Constant(propValue);
// 創建一個不相等比較Expression
BinaryExpression binary = Expression.LessThanOrEqual(member, constant);
// 生成lambda表達式
return Expression.Lambda<Func<T, bool>>(binary, parameter);
}
/// <summary>
/// lambda表達式:t=>t.propName>propValue
/// 多用於where條件
/// </summary>
/// <typeparam name="T">參數類型</typeparam>
/// <param name="propName">屬性名稱</param>
/// <param name="propValue">屬性值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> GreaterThan(string propName, string propValue)
{
// 創建節點參數t
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
// 創建一個成員(字段/屬性)
MemberExpression member = Expression.PropertyOrField(parameter, propName);
// 創建一個常數
ConstantExpression constant = Expression.Constant(propValue);
// 創建一個不相等比較Expression
BinaryExpression binary = Expression.GreaterThan(member, constant);
// 生成lambda表達式
return Expression.Lambda<Func<T, bool>>(binary, parameter);
}
/// <summary>
/// lambda表達式:t=>t.propName>=propValue
/// 多用於where條件
/// </summary>
/// <typeparam name="T">參數類型</typeparam>
/// <param name="propName">屬性名稱</param>
/// <param name="propValue">屬性值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> GreaterThanOrEqual(string propName, string propValue)
{
// 創建節點參數t
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
// 創建一個成員(字段/屬性)
MemberExpression member = Expression.PropertyOrField(parameter, propName);
// 創建一個常數
ConstantExpression constant = Expression.Constant(propValue);
// 創建一個不相等比較Expression
BinaryExpression binary = Expression.GreaterThanOrEqual(member, constant);
// 生成lambda表達式
return Expression.Lambda<Func<T, bool>>(binary, parameter);
}
/// <summary>
/// lambda表達式:t=>{t.contains(propvalue1) ||...||t.contains(propvalueN)}
/// 多用於where條件
/// </summary>
/// <typeparam name="T">參數類型</typeparam>
/// <param name="propName">屬性名稱</param>
/// <param name="propValues">屬性值數組</param>
/// <returns></returns>
public static Expression<Func<T, bool>> In(string propName, string[] propValues)
{
// 創建節點參數t
ParameterExpression parameter = Expression.Parameter(typeof(T), "t"); // left
// 創建一個成員(字段/屬性)
MemberExpression member = Expression.PropertyOrField(parameter, propName);
// 創建一個常數
Expression constant = Expression.Constant(false);
// 創建一個方法
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
foreach (string item in propValues)
{
// 創建一個帶參數方法Expression
MethodCallExpression methodCall = Expression.Call(member, method, Expression.Constant(item)); // right
// 連接參數方法
constant = Expression.Or(methodCall, constant);
}
// 生成lambda表達式
return Expression.Lambda<Func<T, bool>>(constant, new ParameterExpression[] { parameter });
}
/// <summary>
/// lambda表達式:t=>{!(t.contains(propvalue1) ||...||t.contains(propvalueN))}
/// 多用於where條件
/// </summary>
/// <typeparam name="T">參數類型</typeparam>
/// <param name="propName">屬性名稱</param>
/// <param name="propValues">屬性值數組</param>
/// <returns></returns>
public static Expression<Func<T, bool>> NotIn(string propName, string[] propValues)
{
// 創建節點參數t
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
// 創建一個成員(字段/屬性)
MemberExpression member = Expression.PropertyOrField(parameter, propName);
// 創建一個常數
Expression constant = Expression.Constant(false);
// 創建一個方法
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
foreach (string item in propValues)
{
// 創建一個帶參數方法Expression
MethodCallExpression methodCall = Expression.Call(member, method, Expression.Constant(item)); // right
// 連接參數方法
constant = Expression.Or(methodCall, constant);
}
// 生成lambda表達式
return Expression.Lambda<Func<T, bool>>(Expression.Not(constant), new ParameterExpression[] { parameter });
}
/// <summary>
/// lambda表達式:t=>t.propName.Contains(propValue)
/// 多用於where條件
/// </summary>
/// <typeparam name="T">參數類型</typeparam>
/// <param name="propName">屬性名稱</param>
/// <param name="propValue">屬性值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> Contains(string propName, object propValue)
{
// 創建節點參數t
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
// 創建一個成員(字段/屬性)
MemberExpression member = Expression.PropertyOrField(parameter, propName);
// 創建一個常數
ConstantExpression constant = Expression.Constant(propValue, typeof(string));
// 創建一個方法
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
// 創建一個帶參數方法Expression
MethodCallExpression methodCall = Expression.Call(member, method, constant);
// 生成lambda表達式
return Expression.Lambda<Func<T, bool>>(methodCall, parameter);
}
/// <summary>
/// lambda表達式:t=>t.propName.Contains(propValue)
/// 多用於where條件
/// </summary>
/// <typeparam name="T">參數類型</typeparam>
/// <param name="propName">屬性名稱</param>
/// <param name="propValue">屬性值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> StartWith(string propName, object propValue)
{
// 創建節點參數t
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
// 創建一個成員(字段/屬性)
MemberExpression member = Expression.PropertyOrField(parameter, propName);
// 創建一個常數
ConstantExpression constant = Expression.Constant(propValue, typeof(string));
// 創建一個方法
MethodInfo method = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
// 創建一個帶參數方法Expression
MethodCallExpression methodCall = Expression.Call(member, method, constant);
// 生成lambda表達式
return Expression.Lambda<Func<T, bool>>(methodCall, parameter);
}
/// <summary>
/// lambda表達式:t=>t.propName.Contains(propValue)
/// 多用於where條件
/// </summary>
/// <typeparam name="T">參數類型</typeparam>
/// <param name="propName">屬性名稱</param>
/// <param name="propValue">屬性值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> EndsWith(string propName, object propValue)
{
// 創建節點參數t
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
// 創建一個成員(字段/屬性)
MemberExpression member = Expression.PropertyOrField(parameter, propName);
// 創建一個常數
ConstantExpression constant = Expression.Constant(propValue, typeof(string));
// 創建一個方法
MethodInfo method = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
// 創建一個帶參數方法Expression
MethodCallExpression methodCall = Expression.Call(member, method, constant);
// 生成lambda表達式
return Expression.Lambda<Func<T, bool>>(methodCall, parameter);
}
/// <summary>
/// lambda表達式:!(t=>t.propName.Contains(propValue))
/// 多用於where條件
/// </summary>
/// <typeparam name="T">參數類型</typeparam>
/// <param name="propName">屬性名稱</param>
/// <param name="propValue">屬性值</param>
/// <returns></returns>
public static Expression<Func<T, bool>> NotContains(string propName, object propValue)
{
// 創建節點參數t
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
// 創建一個成員(字段/屬性)
MemberExpression member = Expression.PropertyOrField(parameter, propName);
// 創建一個常數
ConstantExpression constant = Expression.Constant(propValue, typeof(string));
// 創建一個方法
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
// 創建一個帶參數方法Expression
MethodCallExpression methodCall = Expression.Call(member, method, constant);
// 生成lambda表達式
return Expression.Lambda<Func<T, bool>>(Expression.Not(methodCall), parameter);
}
/// <summary>
/// lambda表達式:t=>{left and right}
/// 多用於where條件
/// </summary>
/// <param name="left">左側條件</param>
/// <param name="right">右側條件</param>
/// <returns></returns>
public static Expression<Func<T, bool>> And(Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
{
// 創建參數表達式
InvocationExpression invocation = Expression.Invoke(right, left.Parameters.Cast<Expression>());
// 創建and運算
BinaryExpression binary = Expression.And(left.Body, invocation);
// 生成lambda表達式
return Expression.Lambda<Func<T, bool>>(binary, left.Parameters);
}
/// <summary>
/// lambda表達式:t=>{left or right}
/// 多用於where條件
/// </summary>
/// <param name="left">左側條件</param>
/// <param name="right">右側條件</param>
/// <returns></returns>
public static Expression<Func<T, bool>> Or(Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
{
// 創建參數表達式
InvocationExpression invocation = Expression.Invoke(right, left.Parameters.Cast<Expression>());
// 創建or運算
BinaryExpression binary = Expression.Or(left.Body, invocation);
// 生成lambda表達式
return Expression.Lambda<Func<T, bool>>(binary, left.Parameters);
}
}