You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
5.6 KiB

1 year ago
using CK.SCP.Utils;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
namespace ChangkeTec.Utils
{
public static class LinqHelper
{
public static Expression<Func<T, bool>> GetFilterExpression<T>(List<FilterModel> filterConditionList)
{
Expression<Func<T, bool>> condition = null;
try
{
if (filterConditionList != null && filterConditionList.Count > 0)
{
foreach (FilterModel filterCondition in filterConditionList)
{
Expression<Func<T, bool>> tempCondition = CreateLambda<T>(filterCondition);
if (condition == null)
{
condition = tempCondition;
}
else
{
if ("AND".Equals(filterCondition.Logic))
{
condition = condition.And(tempCondition);
}
else
{
condition = condition.Or(tempCondition);
}
}
}
}
}
catch (Exception ex)
{
LogHelper.Write($"获取筛选条件异常:{ex.Message}");
}
return condition;
}
private static Expression<Func<T, bool>> CreateLambda<T>(FilterModel filterCondition)
{
var parameter = Expression.Parameter(typeof(T), "p");//创建参数i
var constant = Expression.Constant(filterCondition.Value);//创建常数
MemberExpression member = Expression.PropertyOrField(parameter, filterCondition.Column);
if ("==".Equals(filterCondition.Action))
{
return Expression.Lambda<Func<T, bool>>(Expression.Equal(member, constant), parameter);
}
else if ("!=".Equals(filterCondition.Action))
{
return Expression.Lambda<Func<T, bool>>(Expression.NotEqual(member, constant), parameter);
}
else if (">".Equals(filterCondition.Action))
{
return Expression.Lambda<Func<T, bool>>(Expression.GreaterThan(member, constant), parameter);
}
else if ("<".Equals(filterCondition.Action))
{
return Expression.Lambda<Func<T, bool>>(Expression.LessThan(member, constant), parameter);
}
else if (">=".Equals(filterCondition.Action))
{
return Expression.Lambda<Func<T, bool>>(Expression.GreaterThanOrEqual(member, constant), parameter);
}
else if ("<=".Equals(filterCondition.Action))
{
return Expression.Lambda<Func<T, bool>>(Expression.LessThanOrEqual(member, constant), parameter);
}
//else if ("in".Equals(filterCondition.Action) && "1".Equals(filterCondition.DataType))
//{
// return GetExpressionWithMethod<T>("Contains", filterCondition);
//}
//else if ("out".Equals(filterCondition.Action) && "1".Equals(filterCondition.DataType))
//{
// return GetExpressionWithoutMethod<T>("Contains", filterCondition);
//}
else
{
return null;
}
}
private static Expression<Func<T, bool>> GetExpressionWithMethod<T>(string methodName, FilterModel filterCondition)
{
ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "p");
MethodCallExpression methodExpression = GetMethodExpression(methodName, filterCondition.Column, filterCondition.Value, parameterExpression);
return Expression.Lambda<Func<T, bool>>(methodExpression, parameterExpression);
}
private static Expression<Func<T, bool>> GetExpressionWithoutMethod<T>(string methodName, FilterModel filterCondition)
{
ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "p");
MethodCallExpression methodExpression = GetMethodExpression(methodName, filterCondition.Column, filterCondition.Value, parameterExpression);
var notMethodExpression = Expression.Not(methodExpression);
return Expression.Lambda<Func<T, bool>>(notMethodExpression, parameterExpression);
}
/// <summary>
/// 生成类似于p=>p.values.Contains("xxx");的lambda表达式
/// parameterExpression标识p,propertyName表示values,propertyValue表示"xxx",methodName表示Contains
/// 仅处理p的属性类型为string这种情况
/// </summary>
/// <param name="methodName"></param>
/// <param name="propertyName"></param>
/// <param name="propertyValue"></param>
/// <param name="parameterExpression"></param>
/// <returns></returns>
private static MethodCallExpression GetMethodExpression(string methodName, string propertyName, string propertyValue, ParameterExpression parameterExpression)
{
var propertyExpression = Expression.Property(parameterExpression, propertyName);
MethodInfo method = typeof(string).GetMethod(methodName, new[] { typeof(string) });
var someValue = Expression.Constant(propertyValue, typeof(string));
return Expression.Call(propertyExpression, method, someValue);
}
}
}