定义接收参数的数据类型
public class DataFilter
{
public string Name { get; set; }
public string Option { get; set; }
public string Value { get; set; }
public List<string> ValueList { get; set; }
}
public enum BasicDataType
{
Int32,
Int64,
Single,
Double,
Decimal,
Boolean,
String,
DateTime
}
public enum OperatorEnum
{
// 等于
OPT_EQ,
// 不等于
OPT_NQ,
// 包含
OPT_LIKE,
// 不包含
OPT_NOTLIKE,
// 大于
OPT_GT,
// 大于等于
OPT_GE,
// 小于
OPT_LT,
// 小于等于
OPT_LE,
// 数组包含
OPT_IN,
// 数组不包含
OPT_NOTIN,
}
Expression 解析器
namespace XXX
{
/// <summary>
/// 前端过滤条件转换为Expression供EFCore使用
/// </summary>
/// <typeparam name="T"></typeparam>
public static class DataFilterConvertor<T> where T : class
{
/// <summary>
/// 入口方法,把数据过滤器转换为Expression
/// </summary>
/// <param name="dataFilterList"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> ToExpression(List<DataFilter> dataFilterList)
{
if (dataFilterList == null || dataFilterList.Count < 1)
{
return (T) => true;
}
ParameterExpression parameterExpression = Expression.Parameter(typeof(T));
Expression firstLambdaExpression = GetSingleFilterExpression(parameterExpression, dataFilterList[0]);
Expression binaryExpression = Expression.AndAlso(Expression.Constant(true), firstLambdaExpression);
foreach (DataFilter dataFilter in dataFilterList.Skip(1))
{
Expression lambdaExpression = GetSingleFilterExpression(parameterExpression, dataFilter);
binaryExpression = Expression.AndAlso(binaryExpression, lambdaExpression);
}
return Expression.Lambda<Func<T, bool>>(binaryExpression, parameterExpression);
}
/// <summary>
/// 获取单个过滤条件的Expression
/// </summary>
/// <param name="parameterExpression"></param>
/// <param name="dataFilter"></param>
/// <returns></returns>
private static Expression GetSingleFilterExpression(ParameterExpression parameterExpression, DataFilter dataFilter)
{
MemberExpression memberExpression = null;
if (dataFilter.Name.Contains('.'))
{
string[] multiLevelProperties = dataFilter.Name.Split('.');
memberExpression = Expression.Property(parameterExpression, multiLevelProperties[0].ToString());
foreach (string propertyName in multiLevelProperties.Skip(1))
{
memberExpression = Expression.Property(memberExpression, propertyName);
}
}
else
{
memberExpression = Expression.Property(parameterExpression, dataFilter.Name);
}
ConstantExpression constantExpression = null;
if (!string.IsNullOrEmpty(dataFilter.Value))
{
dynamic formatedValue = DataValueFormat(dataFilter.Value, memberExpression.Type.Name);
constantExpression = Expression.Constant(formatedValue, memberExpression.Type);
}
else
{
constantExpression = Expression.Constant(dataFilter.ValueList, GetGenericListType(memberExpression.Type.Name));
if (memberExpression.Type.Name == "String")
{
constantExpression = Expression.Constant(dataFilter.ValueList, typeof(List<string>));
}
else
{
constantExpression = Expression.Constant(dataFilter.ValueList, typeof(List<int>));
}
}
Expression body = CreateExpressionBody(memberExpression, constantExpression, dataFilter.Option);
return body;
}
/// <summary>
/// 根据字段,比较值获取Expression
/// </summary>
/// <param name="memberExpression"></param>
/// <param name="constantExpression"></param>
/// <param name="operatorStr"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
private static Expression CreateExpressionBody(
MemberExpression memberExpression, ConstantExpression constantExpression, string operatorStr)
{
if (!Enum.TryParse($"OPT_{operatorStr}".ToUpper(), true, out OperatorEnum operatorEnum))
{
throw new ArgumentException($"不支持操作符:{operatorStr}");
}
Type genericListType = null;
switch (operatorEnum)
{
case OperatorEnum.OPT_EQ:
return Expression.Equal(memberExpression, constantExpression);
case OperatorEnum.OPT_NQ:
return Expression.NotEqual(memberExpression, constantExpression);
case OperatorEnum.OPT_LIKE:
return Expression.Call(memberExpression, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), constantExpression);
case OperatorEnum.OPT_NOTLIKE:
return Expression.Not(Expression.Call(memberExpression, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), constantExpression));
case OperatorEnum.OPT_GT:
case OperatorEnum.OPT_GE:
case OperatorEnum.OPT_LT:
case OperatorEnum.OPT_LE:
return GetCompareExpression(memberExpression, constantExpression, operatorEnum);
case OperatorEnum.OPT_IN:
genericListType = GetGenericListType(memberExpression.Type.Name);
return Expression.Call(constantExpression, genericListType.GetMethod("Contains", new Type[] { memberExpression.Type }), memberExpression);
case OperatorEnum.OPT_NOTIN:
genericListType = GetGenericListType(memberExpression.Type.Name);
return Expression.Not(Expression.Call(constantExpression, genericListType.GetMethod("Contains", new Type[] { memberExpression.Type }), memberExpression));
default:
throw new ArgumentException($"不支持操作符:{operatorEnum}");
}
}
/// <summary>
/// 获取比较表达式,支持字符串、数字、日期比较大小
/// </summary>
/// <param name="memberExpression"></param>
/// <param name="constantExpression"></param>
/// <param name="operatorEnum"></param>
/// <returns></returns>
private static Expression GetCompareExpression(MemberExpression memberExpression, ConstantExpression constantExpression, OperatorEnum operatorEnum)
{
ConstantExpression constant0Expression = Expression.Constant(0);
Expression strCompareExpression = null;
if (memberExpression.Type.Name == BasicDataType.String.ToString())
{
strCompareExpression = Expression.Call(memberExpression, typeof(string).GetMethod("CompareTo", new Type[] { typeof(string) }), constantExpression);
}
switch (operatorEnum)
{
case OperatorEnum.OPT_GT:
if (memberExpression.Type.Name == BasicDataType.String.ToString())
{
return Expression.GreaterThan(strCompareExpression, constant0Expression);
}
else
{
return Expression.GreaterThan(memberExpression, constantExpression);
}
case OperatorEnum.OPT_GE:
if (memberExpression.Type.Name == BasicDataType.String.ToString())
{
return Expression.GreaterThanOrEqual(strCompareExpression, constant0Expression);
}
else
{
return Expression.GreaterThanOrEqual(memberExpression, constantExpression);
}
case OperatorEnum.OPT_LT:
if (memberExpression.Type.Name == BasicDataType.String.ToString())
{
return Expression.LessThan(strCompareExpression, constant0Expression);
}
else
{
return Expression.LessThan(memberExpression, constantExpression);
}
case OperatorEnum.OPT_LE:
if (memberExpression.Type.Name == BasicDataType.String.ToString())
{
return Expression.LessThanOrEqual(strCompareExpression, constant0Expression);
}
else
{
return Expression.LessThanOrEqual(memberExpression, constantExpression);
}
default:
return null;
}
}
/// <summary>
/// 根据属性类型对获取list泛型类型
/// </summary>
/// <param name="typeName"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
private static Type GetGenericListType(string typeName)
{
if (!Enum.TryParse(typeName, true, out BasicDataType dataType))
{
throw new ArgumentException($"不支的数据类型:{typeName}");
}
switch (dataType)
{
case BasicDataType.String:
return typeof(List<string>);
case BasicDataType.Int32:
return typeof(List<string>);
default:
throw new ArgumentException("不支持的泛型类型转换");
}
}
/// <summary>
/// 输入value值根据对应的属性类型格式化
/// </summary>
/// <param name="value"></param>
/// <param name="typeName"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="Exception"></exception>
private static dynamic DataValueFormat(string value, string typeName)
{
if (!Enum.TryParse(typeName, true, out BasicDataType dataType))
{
throw new ArgumentException($"不支的数据类型:{typeName}");
}
switch (dataType)
{
case BasicDataType.Int32:
return Convert.ToInt32(value);
case BasicDataType.Int64:
return Convert.ToInt64(value);
case BasicDataType.Single:
return Convert.ToSingle(value);
case BasicDataType.Double:
return Convert.ToDouble(value);
case BasicDataType.Decimal:
return Convert.ToDecimal(value);
case BasicDataType.String:
return value;
case BasicDataType.DateTime:
return Convert.ToDateTime(value);
case BasicDataType.Boolean:
value = value.ToUpper();
if (value == "TRUE" || value == "1")
{
return true;
}
else if (value == "FALSE" || value == "0")
{
return false;
}
else
{
throw new Exception($"{value}不能被解析为Bool类型");
}
default:
throw new Exception($"{value}不能被解析为{typeName}类型");
}
}
}
}
调用
//...
Expression<Func<StructureModel, bool>> expression =
DataFilterConvertor<StructureModel>.ToExpression(requestVM.DataFilterList);
List<StructureModel> modelList = structureService.FindPageList(requestVM.PageIndex,
requestVM.PageSize, out totalCount, expression, "id", true).ToList();
//...
网友评论