using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Linq.Expressions;
|
using System.Reflection;
|
using System.Text;
|
using System.Threading.Tasks;
|
using WIDESEA_Core.Enums;
|
using WIDESEA_Core.Helper;
|
|
namespace WIDESEA_Core.Utilities
|
{
|
public static class LambdaExtensions
|
{
|
/// <summary>
|
///
|
/// </summary>
|
/// <typeparam name="T"></typeparam>
|
/// <param name="propertyName">字段名</param>
|
/// <param name="propertyValue">表达式的值</param>
|
/// <param name="expressionType">创建表达式的类型,如:p=>p.propertyName != propertyValue
|
/// p=>p.propertyName.Contains(propertyValue)</param>
|
/// <returns></returns>
|
public static Expression<Func<T, bool>> CreateExpression<T>(this string propertyName, object propertyValue, LinqExpressionType expressionType)
|
{
|
return propertyName.CreateExpression<T>(propertyValue, null, expressionType);
|
}
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <typeparam name="T"></typeparam>
|
/// <param name="propertyName">字段名</param>
|
/// <param name="propertyValue">表达式的值</param>
|
/// <param name="expressionType">创建表达式的类型,如:p=>p.propertyName != propertyValue
|
/// p=>p.propertyName.Contains(propertyValue)</param>
|
/// <returns></returns>
|
private static Expression<Func<T, bool>> CreateExpression<T>(
|
this string propertyName,
|
object propertyValue,
|
ParameterExpression parameter,
|
LinqExpressionType expressionType)
|
{
|
Type proType = null;
|
PropertyInfo propertyInfo = typeof(T).GetProperty(propertyName);
|
if (propertyInfo != null)
|
proType = propertyInfo.PropertyType;
|
else
|
{
|
propertyInfo = typeof(T).GetProperty(propertyName.FirstLetterToLower());
|
if (propertyInfo != null)
|
proType = propertyInfo.PropertyType;
|
else
|
{
|
propertyInfo = typeof(T).GetProperty(propertyName.FirstLetterToUpper());
|
if (propertyInfo != null)
|
proType = propertyInfo.PropertyType;
|
else
|
{
|
throw new Exception($"未找到该属性,type:{typeof(T)}");
|
}
|
}
|
}
|
//创建节点变量如p=>的节点p
|
// parameter ??= Expression.Parameter(typeof(T), "p");//创建参数p
|
parameter = parameter ?? Expression.Parameter(typeof(T), "p");
|
|
//创建节点的属性p=>p.name 属性name
|
MemberExpression memberProperty = Expression.PropertyOrField(parameter, propertyName);
|
if (expressionType == LinqExpressionType.In)
|
{
|
if (!(propertyValue is System.Collections.IList list) || list.Count == 0) throw new Exception("属性值类型不正确");
|
|
bool isStringValue = true;
|
List<object> objList = new List<object>();
|
|
if (proType.ToString() != "System.String")
|
{
|
isStringValue = false;
|
foreach (var value in list)
|
{
|
objList.Add(value.ToString().ChangeType(proType));
|
}
|
list = objList;
|
}
|
|
if (isStringValue)
|
{
|
//string 类型的字段,如果值带有'单引号,EF会默认变成''两个单引号
|
MethodInfo method = typeof(System.Collections.IList).GetMethod("Contains");
|
//创建集合常量并设置为常量的值
|
ConstantExpression constantCollection = Expression.Constant(list);
|
//创建一个表示调用带参数的方法的:new string[]{"1","a"}.Contains("a");
|
MethodCallExpression methodCall = Expression.Call(constantCollection, method, memberProperty);
|
return Expression.Lambda<Func<T, bool>>(methodCall, parameter);
|
}
|
//非string字段,按上面方式处理报异常Null TypeMapping in Sql Tree
|
BinaryExpression body = null;
|
foreach (var value in list)
|
{
|
ConstantExpression constantExpression = Expression.Constant(value);
|
UnaryExpression unaryExpression = Expression.Convert(memberProperty, constantExpression.Type);
|
|
body = body == null
|
? Expression.Equal(unaryExpression, constantExpression)
|
: Expression.OrElse(body, Expression.Equal(unaryExpression, constantExpression));
|
}
|
return Expression.Lambda<Func<T, bool>>(body, parameter);
|
}
|
|
// object value = propertyValue;
|
ConstantExpression constant = proType.ToString() == "System.String"
|
? Expression.Constant(propertyValue) : Expression.Constant(propertyValue.ToString().ChangeType(proType));
|
|
// DateTime只选择了日期的时候自动在结束日期加一天,修复DateTime类型使用日期区间查询无法查询到结束日期的问题
|
if ((proType == typeof(DateTime) || proType == typeof(DateTime?)) && expressionType == LinqExpressionType.LessThanOrEqual && propertyValue.ToString().Length == 10)
|
{
|
constant = Expression.Constant(Convert.ToDateTime(propertyValue.ToString()).AddDays(1));
|
}
|
|
UnaryExpression member = Expression.Convert(memberProperty, constant.Type);
|
Expression<Func<T, bool>> expression;
|
switch (expressionType)
|
{
|
//p=>p.propertyName == propertyValue
|
case LinqExpressionType.Equal:
|
expression = Expression.Lambda<Func<T, bool>>(Expression.Equal(member, constant), parameter);
|
break;
|
//p=>p.propertyName != propertyValue
|
case LinqExpressionType.NotEqual:
|
expression = Expression.Lambda<Func<T, bool>>(Expression.NotEqual(member, constant), parameter);
|
break;
|
// p => p.propertyName > propertyValue
|
case LinqExpressionType.GreaterThan:
|
expression = Expression.Lambda<Func<T, bool>>(Expression.GreaterThan(member, constant), parameter);
|
break;
|
// p => p.propertyName < propertyValue
|
case LinqExpressionType.LessThan:
|
expression = Expression.Lambda<Func<T, bool>>(Expression.LessThan(member, constant), parameter);
|
break;
|
// p => p.propertyName >= propertyValue
|
case LinqExpressionType.ThanOrEqual:
|
expression = Expression.Lambda<Func<T, bool>>(Expression.GreaterThanOrEqual(member, constant), parameter);
|
break;
|
// p => p.propertyName <= propertyValue
|
case LinqExpressionType.LessThanOrEqual:
|
expression = Expression.Lambda<Func<T, bool>>(Expression.LessThanOrEqual(member, constant), parameter);
|
break;
|
// p => p.propertyName.Contains(propertyValue)
|
// p => !p.propertyName.Contains(propertyValue)
|
case LinqExpressionType.Contains:
|
case LinqExpressionType.NotContains:
|
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
|
constant = Expression.Constant(propertyValue, typeof(string));
|
if (expressionType == LinqExpressionType.Contains)
|
{
|
expression = Expression.Lambda<Func<T, bool>>(Expression.Call(member, method, constant), parameter);
|
}
|
else
|
{
|
expression = Expression.Lambda<Func<T, bool>>(Expression.Not(Expression.Call(member, method, constant)), parameter);
|
}
|
break;
|
default:
|
// p => p.false
|
expression = False<T>();
|
break;
|
}
|
return expression;
|
}
|
|
/// <summary>
|
/// 创建lambda表达式:p=>false
|
/// </summary>
|
/// <typeparam name="T"></typeparam>
|
/// <returns></returns>
|
public static Expression<Func<T, bool>> False<T>()
|
{
|
|
return p => false;
|
}
|
|
public static Expression<Func<TEntity, bool>> GetWhereExpression<TEntity>(this PropertyInfo propertyInfo, object propertyValue, ParameterExpression parameter, LinqExpressionType expressionType)
|
{
|
Type proType = propertyInfo.PropertyType;
|
ConstantExpression constant = proType.ToString() == "System.String"
|
? Expression.Constant(propertyValue) : Expression.Constant(propertyValue.ToString().ChangeType(proType));
|
|
// DateTime只选择了日期的时候自动在结束日期加一天,修复DateTime类型使用日期区间查询无法查询到结束日期的问题
|
if ((proType == typeof(DateTime) || proType == typeof(DateTime?)) && expressionType == LinqExpressionType.LessThanOrEqual && propertyValue.ToString().Length == 10)
|
{
|
constant = Expression.Constant(Convert.ToDateTime(propertyValue.ToString()).AddDays(1));
|
}
|
parameter = parameter ?? Expression.Parameter(typeof(TEntity), "b");
|
//创建节点的属性p=>p.name 属性name
|
MemberExpression memberProperty = Expression.PropertyOrField(parameter, propertyInfo.Name);
|
UnaryExpression member = Expression.Convert(memberProperty, constant.Type);
|
Expression<Func<TEntity, bool>> expression = p => false;
|
switch (expressionType)
|
{
|
//p=>p.propertyName == propertyValue
|
case LinqExpressionType.Equal:
|
expression = Expression.Lambda<Func<TEntity, bool>>(Expression.Equal(member, constant), parameter);
|
break;
|
//p=>p.propertyName != propertyValue
|
case LinqExpressionType.NotEqual:
|
expression = Expression.Lambda<Func<TEntity, bool>>(Expression.NotEqual(member, constant), parameter);
|
break;
|
// p => p.propertyName > propertyValue
|
case LinqExpressionType.GreaterThan:
|
expression = Expression.Lambda<Func<TEntity, bool>>(Expression.GreaterThan(member, constant), parameter);
|
break;
|
// p => p.propertyName < propertyValue
|
case LinqExpressionType.LessThan:
|
expression = Expression.Lambda<Func<TEntity, bool>>(Expression.LessThan(member, constant), parameter);
|
break;
|
// p => p.propertyName >= propertyValue
|
case LinqExpressionType.ThanOrEqual:
|
expression = Expression.Lambda<Func<TEntity, bool>>(Expression.GreaterThanOrEqual(member, constant), parameter);
|
break;
|
// p => p.propertyName <= propertyValue
|
case LinqExpressionType.LessThanOrEqual:
|
expression = Expression.Lambda<Func<TEntity, bool>>(Expression.LessThanOrEqual(member, constant), parameter);
|
break;
|
// p => p.propertyName.Contains(propertyValue)
|
// p => !p.propertyName.Contains(propertyValue)
|
case LinqExpressionType.Contains:
|
case LinqExpressionType.NotContains:
|
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
|
constant = Expression.Constant(propertyValue, typeof(string));
|
if (expressionType == LinqExpressionType.Contains)
|
{
|
expression = Expression.Lambda<Func<TEntity, bool>>(Expression.Call(member, method, constant), parameter);
|
}
|
else
|
{
|
expression = Expression.Lambda<Func<TEntity, bool>>(Expression.Not(Expression.Call(member, method, constant)), parameter);
|
}
|
break;
|
default:
|
//
|
expression = p => false;
|
break;
|
}
|
return expression;
|
}
|
}
|
}
|