using SignUp.Common.Enum; using SignUp.Common.Extensions; namespace SignUp.Common.DataFilter { /// <summary> /// 参数转换 /// </summary> public static class FormatParameters { public static List<DataFilter> GetSearchParameters( string wheres) { List<DataFilter> searchParametersList = new List<DataFilter>(); if (! string .IsNullOrEmpty(wheres)) { try { searchParametersList = wheres.DeserializeObject<List<DataFilter>>(); } catch { } } return searchParametersList; } public static Dictionary< string , QueryOrderBy> GetOrderParameters( string sort, string order) { Dictionary< string , QueryOrderBy> orderBy = new Dictionary< string , QueryOrderBy>(); if (order.ToLower() == "desc" ) orderBy.Add(sort, QueryOrderBy.Desc); else orderBy.Add(sort, QueryOrderBy.Asc); return orderBy; } } } using SignUp.Common.Enum; using System.Linq.Expressions; namespace SignUp.Common.DataFilter { /// <summary> /// 前端查询条件转换为Expression供EFCore使用 /// </summary> /// <typeparam name="T"></typeparam> public static class DataFilterConvertor<T> where T : class { #region 查询条件 /// <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)) { string fieldsType = "" ; if (memberExpression.Type.FullName.IndexOf( "DateTime" ) != -1) fieldsType = "DateTime" ; else if (memberExpression.Type.FullName.IndexOf( "System.Guid" ) != -1) fieldsType = "Guid" ; else fieldsType = memberExpression.Type.Name; dynamic formatedValue = DataValueFormat(dataFilter.Value, fieldsType); 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 (!System.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 (!System.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 (!System.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.Guid: return Guid.Parse(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}类型" ); } } #endregion } } using SignUp.Common.Enum; using System.Linq.Expressions; namespace SignUp.Common.DataFilter { /// <summary> /// 动态实现排序 /// </summary> public static class DataOrderConvertor { /// <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 ; } public static ParameterExpression GetExpressionParameter( this Type type) { return Expression.Parameter(type, "p" ); } /// <summary> /// 创建lambda表达式:p=>p.propertyName /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="TKey"></typeparam> /// <param name="sort"></param> /// <returns></returns> public static Expression<Func<T, TKey>> GetExpression<T, TKey>( this string propertyName) { return propertyName.GetExpression<T, TKey>( typeof (T).GetExpressionParameter()); } /// <summary> /// 创建委托有返回值的表达式:p=>p.propertyName /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="TKey"></typeparam> /// <param name="sort"></param> /// <returns></returns> public static Func<T, TKey> GetFun<T, TKey>( this string propertyName) { return propertyName.GetExpression<T, TKey>( typeof (T).GetExpressionParameter()).Compile(); } /// <summary> /// 创建lambda表达式:p=>false /// 在已知TKey字段类型时,如动态排序OrderBy(x=>x.ID)会用到此功能,返回的就是x=>x.ID /// Expression<Func<Out_Scheduling, DateTime>> expression = x => x.CreateDate;指定了类型 /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public static Expression<Func<T, TKey>> GetExpression<T, TKey>( this string propertyName, ParameterExpression parameter) { if ( typeof (TKey).Name == "Object" ) return Expression.Lambda<Func<T, TKey>>(Expression.Convert(Expression.Property(parameter, propertyName), typeof ( object )), parameter); return Expression.Lambda<Func<T, TKey>>(Expression.Property(parameter, propertyName), parameter); } /// <summary> /// 创建lambda表达式:p=>false /// object不能确认字段类型(datetime,int,string),如动态排序OrderBy(x=>x.ID)会用到此功能,返回的就是x=>x.ID /// Expression<Func<Out_Scheduling, object>> expression = x => x.CreateDate;任意类型的字段 /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public static Expression<Func<T, object >> GetExpression<T>( this string propertyName) { return propertyName.GetExpression<T, object >( typeof (T).GetExpressionParameter()); } public static Expression<Func<T, object >> GetExpression<T>( this string propertyName, ParameterExpression parameter) { return Expression.Lambda<Func<T, object >>(Expression.Convert(Expression.Property(parameter, propertyName), typeof ( object )), parameter); } /// <summary> /// 解析多字段排序 /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="queryable"></param> /// <param name="orderBySelector">string=排序的字段,bool=true降序/false升序</param> /// <returns></returns> public static IQueryable<TEntity> OrderConditions<TEntity>( this IQueryable<TEntity> queryable, Dictionary< string , QueryOrderBy> orderBySelector) { string [] orderByKeys = orderBySelector.Select(x => x.Key).ToArray(); if (orderByKeys == null || orderByKeys.Length == 0) return queryable; IOrderedQueryable<TEntity> queryableOrderBy = null ; // string orderByKey = orderByKeys[^1]; string orderByKey = orderByKeys[orderByKeys.Length - 1]; queryableOrderBy = orderBySelector[orderByKey] == QueryOrderBy.Desc ? queryableOrderBy = queryable.OrderByDescending(orderByKey.GetExpression<TEntity>()) : queryable.OrderBy(orderByKey.GetExpression<TEntity>()); for ( int i = orderByKeys.Length - 2; i >= 0; i--) { queryableOrderBy = orderBySelector[orderByKeys[i]] == QueryOrderBy.Desc ? queryableOrderBy.ThenByDescending(orderByKeys[i].GetExpression<TEntity>()) : queryableOrderBy.ThenBy(orderByKeys[i].GetExpression<TEntity>()); } return queryableOrderBy; } } } namespace SignUp.Common.DataFilter { /// <summary> /// FE CORE动态查询条件拼接,接收前台查询条件 /// </summary> public class DataFilter { public string Name { get ; set ; } public string Option { get ; set ; } public string Value { get ; set ; } public List< string > ValueList { get ; set ; } } } namespace SignUp.Common.Enum { /// <summary> /// FE CORE动态查询条件拼接,支持的数据类型 /// </summary> public enum BasicDataType { Int32, Int64, Single, Double, Decimal, Boolean, String, DateTime, Guid } } namespace SignUp.Common.Enum { /// <summary> /// FE CORE动态查询条件拼接,支持的运算符 /// </summary> public enum OperatorEnum { // 等于 OPT_EQ, // 不等于 OPT_NQ, // 包含 OPT_LIKE, // 不包含 OPT_NOTLIKE, // 大于 OPT_GT, // 大于等于 OPT_GE, // 小于 OPT_LT, // 小于等于 OPT_LE, // 数组包含 OPT_IN, // 数组不包含 OPT_NOTIN, } } namespace SignUp.Common.Enum { /// <summary> /// 排序方式 /// </summary> public enum QueryOrderBy { Desc = 1, Asc = 2 } } |