From 53844547d84291c4101627db8cd2b4923d2954df Mon Sep 17 00:00:00 2001 From: ydy <517697206@qq.com> Date: Sat, 22 Jun 2024 12:44:10 +0800 Subject: [PATCH] fix:#170,modify for dynamic GetExpressionItems and add code for expression --- .../OrganizationManage/DepartmentBLL.cs | 6 +- .../OrganizationManage/UserService.cs | 88 ++--- .../YiSha.Model/Param/DateTimeParam.cs | 8 +- .../Param/OrganizationManage/UserParam.cs | 10 +- .../YiSha.Util/Extension/Extension.Linq.cs | 332 +++++++++--------- 5 files changed, 234 insertions(+), 210 deletions(-) diff --git a/YiSha.Business/YiSha.Business/OrganizationManage/DepartmentBLL.cs b/YiSha.Business/YiSha.Business/OrganizationManage/DepartmentBLL.cs index 061231ce..2978495f 100644 --- a/YiSha.Business/YiSha.Business/OrganizationManage/DepartmentBLL.cs +++ b/YiSha.Business/YiSha.Business/OrganizationManage/DepartmentBLL.cs @@ -36,10 +36,10 @@ public async Task>> GetList(DepartmentListParam par List userList = new List(); if (obj.Data.Count > 0) { - var userIdsArr = obj.Data.Where(p => p.PrincipalId > 0).Select(p => p.PrincipalId).ToArray(); - if (userIdsArr.Length > 0) + var userIdsArr = obj.Data.Where(p => p.PrincipalId > 0).Select(p => p.PrincipalId.Value); + if (userIdsArr.Count() > 0) { - userList = await userService.GetList(new UserListParam { UserIds = string.Join(",", userIdsArr) }); + userList = await userService.GetList(new UserListParam { UserIds = userIdsArr.ToArray() }); } } foreach (DepartmentEntity entity in obj.Data) diff --git a/YiSha.Business/YiSha.Service/OrganizationManage/UserService.cs b/YiSha.Business/YiSha.Service/OrganizationManage/UserService.cs index 7dd18152..a40b0c96 100644 --- a/YiSha.Business/YiSha.Service/OrganizationManage/UserService.cs +++ b/YiSha.Business/YiSha.Service/OrganizationManage/UserService.cs @@ -166,50 +166,58 @@ public async Task ChangeUser(UserEntity entity) #region 私有方法 private Expression> ListFilter(UserListParam param) { - //****根据查询字段自动过滤条件**** - var expression = LinqExtensions.GetExpressionItems(param); - - if (param != null) + if(param != null) { - if (param.UserStatus == -1) - { - param.UserStatus = null; - } - //if (!string.IsNullOrEmpty(param.UserName)) - //{ - // expression = expression.And(t => t.UserName.Contains(param.UserName)); - //} - - - if (!string.IsNullOrEmpty(param.UserIds)) + if (!string.IsNullOrEmpty(param.EndTime.ParseToString())) { - long[] userIdList = TextHelper.SplitToArray(param.UserIds, ','); - expression = expression.And(t => userIdList.Contains(t.Id.Value)); - } - - //if (!string.IsNullOrEmpty(param.Mobile)) - //{ - // expression = expression.And(t => t.Mobile.Contains(param.Mobile)); - //} - //if (param.UserStatus > -1) - //{ - // expression = expression.And(t => t.UserStatus == param.UserStatus); - //} - - //if (!string.IsNullOrEmpty(param.StartTime.ParseToString())) - //{ - // expression = expression.And(t => t.BaseModifyTime >= param.StartTime); - //} - //if (!string.IsNullOrEmpty(param.EndTime.ParseToString())) - //{ - // param.EndTime = param.EndTime.Value.Date.Add(new TimeSpan(23, 59, 59)); - // expression = expression.And(t => t.BaseModifyTime <= param.EndTime); - //} - if (param.ChildrenDepartmentIdList != null && param.ChildrenDepartmentIdList.Count > 0) - { - expression = expression.And(t => param.ChildrenDepartmentIdList.Contains(t.DepartmentId.Value)); + param.EndTime = param.EndTime.Value.Date.Add(new TimeSpan(23, 59, 59)); } } + //****根据查询字段自动过滤条件**** + var expression = LinqExtensions.GetExpressionItems(param); + + //if (param != null) + //{ + // //if (param.UserStatus == -1) + // //{ + // // param.UserStatus = null; + // //} + + // //if (!string.IsNullOrEmpty(param.UserName)) + // //{ + // // expression = expression.And(t => t.UserName.Contains(param.UserName)); + // //} + + + // //if (!string.IsNullOrEmpty(param.UserIds)) + // //{ + // // long[] userIdList = TextHelper.SplitToArray(param.UserIds, ','); + // // expression = expression.And(t => userIdList.Contains(t.Id.Value)); + // //} + + // //if (!string.IsNullOrEmpty(param.Mobile)) + // //{ + // // expression = expression.And(t => t.Mobile.Contains(param.Mobile)); + // //} + // //if (param.UserStatus > -1) + // //{ + // // expression = expression.And(t => t.UserStatus == param.UserStatus); + // //} + + // //if (!string.IsNullOrEmpty(param.StartTime.ParseToString())) + // //{ + // // expression = expression.And(t => t.BaseModifyTime >= param.StartTime); + // //} + // //if (!string.IsNullOrEmpty(param.EndTime.ParseToString())) + // //{ + // // param.EndTime = param.EndTime.Value.Date.Add(new TimeSpan(23, 59, 59)); + // // expression = expression.And(t => t.BaseModifyTime <= param.EndTime); + // //} + // //if (param.ChildrenDepartmentIdList != null && param.ChildrenDepartmentIdList.Count > 0) + // //{ + // // expression = expression.And(t => param.ChildrenDepartmentIdList.Contains(t.DepartmentId.Value)); + // //} + //} return expression; } #endregion diff --git a/YiSha.Entity/YiSha.Model/Param/DateTimeParam.cs b/YiSha.Entity/YiSha.Model/Param/DateTimeParam.cs index c0c3486e..58f5ed74 100644 --- a/YiSha.Entity/YiSha.Model/Param/DateTimeParam.cs +++ b/YiSha.Entity/YiSha.Model/Param/DateTimeParam.cs @@ -12,13 +12,13 @@ public class DateTimeParam /// /// 搜索条件开始时间 /// - [LinqExpressionXAttribute(Name = "BaseModifyTime")] - public DateTime? StartTime { get; set; } + [QueryCompareAttribute(FieldName = "BaseModifyTime",Compare =CompareEnum.GreaterThanOrEquals)] + public virtual DateTime? StartTime { get; set; } /// /// 搜索条件结束时间 /// - [LinqExpressionXAttribute(Name = "BaseModifyTime")] - public DateTime? EndTime { get; set; } + [QueryCompareAttribute(FieldName = "BaseModifyTime", Compare = CompareEnum.LessThanOrEquals)] + public virtual DateTime? EndTime { get; set; } } } diff --git a/YiSha.Entity/YiSha.Model/Param/OrganizationManage/UserParam.cs b/YiSha.Entity/YiSha.Model/Param/OrganizationManage/UserParam.cs index 026db2f3..13294bf9 100644 --- a/YiSha.Entity/YiSha.Model/Param/OrganizationManage/UserParam.cs +++ b/YiSha.Entity/YiSha.Model/Param/OrganizationManage/UserParam.cs @@ -8,16 +8,16 @@ namespace YiSha.Model.Param.OrganizationManage public class UserListParam : DateTimeParam { public string UserName { get; set; } - + [QueryCompareAttribute(Compare = CompareEnum.Equals)] public string Mobile { get; set; } - + [QueryCompareAttribute(Compare = CompareEnum.Equals)] public int? UserStatus { get; set; } public long? DepartmentId { get; set; } - [LinqExpressionXAttribute(IsIgnore = true)] + [QueryCompareAttribute(FieldName = "DepartmentId", Compare = CompareEnum.In)] public List ChildrenDepartmentIdList { get; set; } - [LinqExpressionXAttribute(IsIgnore = true)] - public string UserIds { get; set; } + [QueryCompareAttribute(FieldName ="Id",Compare = CompareEnum.In)] + public long[] UserIds { get; set; } } public class ChangePasswordParam diff --git a/YiSha.Util/YiSha.Util/Extension/Extension.Linq.cs b/YiSha.Util/YiSha.Util/Extension/Extension.Linq.cs index ab2b14eb..efaa4bf2 100644 --- a/YiSha.Util/YiSha.Util/Extension/Extension.Linq.cs +++ b/YiSha.Util/YiSha.Util/Extension/Extension.Linq.cs @@ -1,10 +1,15 @@ -using System; +using Microsoft.AspNetCore.JsonPatch.Operations; +using NLog.LayoutRenderers; +using NPOI.SS.Formula.Functions; +using NPOI.Util; +using System; +using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Linq.Expressions; -using System.Text; -using System.Threading.Tasks; +using System.Reflection; +using System.Reflection.Metadata; namespace YiSha.Util.Extension { @@ -79,143 +84,33 @@ private static Expression Compose(this Expression first, Expression /// public static Expression> GetExpressionItems(TT input) { - var parameter = Expression.Parameter(typeof(T), "entity"); - Expression expression = Expression.Constant(true); - if (input != null) + if (input == null) return x => true; + List cndQueryList = new List(); + var allProperty = typeof(TT).GetProperties(); + foreach (var p in allProperty) { - var properties = typeof(TT).GetProperties(); - var targetProperties = typeof(T).GetProperties(); - var linqXAttrType = typeof(LinqExpressionXAttribute); - foreach (var property in properties) + var compareAttr = p.GetCustomAttribute(); + if (compareAttr != null && compareAttr.IsIgnore) continue; + var val = p.GetValue(input,null); + if ( val == null || string.IsNullOrEmpty(val.ToString())) continue; + + //查找和实体映射的属性名和值以及操作符 + string fieldName = p.Name; + CompareEnum compareType = CompareEnum.Equals; + if (compareAttr != null) { - var attrName = property.Name; - //判断属性是否有 LinqExpressionXAttribute 标识,并且如果有则判断是否有忽略标识以及Name名称 - var attrObjList = property.GetCustomAttributes(linqXAttrType, true); - if (attrObjList.Length > 0) - { - var attrObjData = attrObjList[0] as LinqExpressionXAttribute; - if (attrObjData.IsIgnore) - { - continue; - } - if (attrObjData.Name.Length > 0) - { - attrName = attrObjData.Name; - } - } - //字符类型筛选 - if (property.PropertyType == typeof(string)) - { - var value = property.GetValue(input); - if (value != null && !string.IsNullOrEmpty(value.ToString())) - { - var propertyExpression = Expression.Property(parameter, attrName); - //var valueExpression = Expression.Constant(value); - var equalExpression = Expression.Equal(propertyExpression, Expression.Constant(value)); - // var containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) }); - // var containsExpression = Expression.Call(propertyExpression, containsMethod, valueExpression); - expression = Expression.AndAlso(expression, equalExpression); - } - } - //日期类型筛选 - else if (property.PropertyType == typeof(DateTime) || property.PropertyType == typeof(DateTime?)) - { - var value = property.GetValue(input); - - if (value != null) - { - // 开始日期筛选 - if (property.Name.Contains("Start")) - { - //var realPropertyName = attrName.Substring(0, attrName.Length - "Start".Length); - var propertyExpression = Expression.Property(parameter, attrName); - var entityfield = targetProperties.FirstOrDefault(s => s.Name == attrName); - var startDateTime = (DateTime)value; - - if (entityfield.PropertyType == typeof(DateTime?)) - { - var greaterThanOrEqualExpression = Expression.GreaterThanOrEqual(propertyExpression, Expression.Constant(startDateTime, typeof(DateTime?))); - expression = Expression.AndAlso(expression, greaterThanOrEqualExpression); - } - else - { - var greaterThanOrEqualExpression = Expression.GreaterThanOrEqual(propertyExpression, Expression.Constant(startDateTime)); - expression = Expression.AndAlso(expression, greaterThanOrEqualExpression); - } - } - // 结束日期筛选 - else if (property.Name.Contains("End")) - { - //var realPropertyName = attrName.Substring(0, attrName.Length - "End".Length); - var propertyExpression = Expression.Property(parameter, attrName); - var entityfield = targetProperties.FirstOrDefault(s => s.Name == attrName); - var endDateTime = ((DateTime)value).Date.AddDays(1).AddTicks(-1); - - if (entityfield.PropertyType == typeof(DateTime?)) - { - var lessThanOrEqualExpression = Expression.LessThanOrEqual(propertyExpression, Expression.Constant(endDateTime, typeof(DateTime?))); - expression = Expression.AndAlso(expression, lessThanOrEqualExpression); - } - else - { - var lessThanOrEqualExpression = Expression.LessThanOrEqual(propertyExpression, Expression.Constant(endDateTime)); - expression = Expression.AndAlso(expression, lessThanOrEqualExpression); - } - } - // 其他日期属性 - else - { - var propertyExpression = Expression.Property(parameter, attrName); - var equalExpression = Expression.Equal(propertyExpression, Expression.Constant(value)); - expression = Expression.AndAlso(expression, equalExpression); - } - } - } - //数值类型 - else if (property.PropertyType == typeof(int?) || property.PropertyType == typeof(int)) - { - var value = property.GetValue(input); - var propertyExpression = Expression.Property(parameter, attrName); - var entityfield = targetProperties.FirstOrDefault(s => s.Name == attrName); - - if (value != null) - { - if (entityfield.PropertyType == typeof(int?)) - { - var equalExpression = Expression.Equal(propertyExpression, Expression.Constant(value, typeof(int?))); - expression = Expression.AndAlso(expression, equalExpression); - } - else - { - var equalExpression = Expression.Equal(propertyExpression, Expression.Constant(value)); - expression = Expression.AndAlso(expression, equalExpression); - } - } - } - //float - else if (property.PropertyType == typeof(float?) || property.PropertyType == typeof(float)) - { - var value = property.GetValue(input); - var propertyExpression = Expression.Property(parameter, attrName); - var entityfield = targetProperties.FirstOrDefault(s => s.Name == attrName); - - if (value != null) - { - if (entityfield.PropertyType == typeof(float?)) - { - var equalExpression = Expression.Equal(propertyExpression, Expression.Constant(value, typeof(float?))); - expression = Expression.AndAlso(expression, equalExpression); - } - else - { - var equalExpression = Expression.Equal(propertyExpression, Expression.Constant(value)); - expression = Expression.AndAlso(expression, equalExpression); - } - } - } + fieldName = string.IsNullOrWhiteSpace(compareAttr.FieldName) ? p.Name : compareAttr.FieldName; + compareType = compareAttr.Compare; } + cndQueryList.Add(new QueryCompareAttribute() + { + FieldName = fieldName, + Value = val, + Compare = compareType, + }); } - return Expression.Lambda>(expression, parameter); + var exp = BuildAndAlsoLambda(cndQueryList); + return exp; } /// @@ -264,42 +159,163 @@ protected override Expression VisitParameter(ParameterExpression p) return base.VisitParameter(p); } } + + /// + /// + /// + /// + /// + private static bool IsNullable(PropertyInfo propertyInfo) + { + Type propertyType = propertyInfo.PropertyType; + return propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>); + } + + private static Expression GetExpression(ParameterExpression parameter, QueryCompareAttribute condition) + { + var propertyParam = Expression.Property(parameter, condition.FieldName); + + var propertyInfo = propertyParam.Member as PropertyInfo; + if (propertyInfo == null) + throw new MissingMemberException(nameof(QueryCompareAttribute), condition.FieldName); + + //Support Nullable<> + var realPropertyType = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType; + if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) + propertyParam = Expression.Property(propertyParam, "Value"); + + //Support IEnumerable && IEnumerable + if (condition.Compare != CompareEnum.In && condition.Compare != CompareEnum.NotIn) + { + condition.Value = Convert.ChangeType(condition.Value, realPropertyType); + } + else + { + var typeOfValue = condition.Value.GetType(); + var typeOfList = typeof(IEnumerable<>).MakeGenericType(realPropertyType); + if (typeOfValue.IsGenericType && typeOfList.IsAssignableFrom(typeOfValue)) + condition.Value = typeof(Enumerable) + .GetMethod("ToArray", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static) + .MakeGenericMethod(realPropertyType) + .Invoke(null, new object[] { condition.Value }); + } + + var constantParam = Expression.Constant(condition.Value); + switch (condition.Compare) + { + case CompareEnum.Equals: + return Expression.Equal(propertyParam, constantParam); + + case CompareEnum.NotEquals: + return Expression.NotEqual(propertyParam, constantParam); + + case CompareEnum.Contains: + return Expression.Call(propertyParam, "Contains", null, constantParam); ; + case CompareEnum.NotContains: + return Expression.Not(Expression.Call(propertyParam, "Contains", null, constantParam)); + + case CompareEnum.StartsWith: + return Expression.Call(propertyParam, "StartsWith", null, constantParam); + + case CompareEnum.EndsWith: + return Expression.Call(propertyParam, "EndsWith", null, constantParam); + + case CompareEnum.GreaterThan: + return Expression.GreaterThan(propertyParam, constantParam); + + case CompareEnum.GreaterThanOrEquals: + return Expression.GreaterThanOrEqual(propertyParam, constantParam); + + case CompareEnum.LessThan: + return Expression.LessThan(propertyParam, constantParam); + + case CompareEnum.LessThanOrEquals: + return Expression.LessThanOrEqual(propertyParam, constantParam); + + case CompareEnum.In: + return Expression.Call(typeof(Enumerable), "Contains", new Type[] { realPropertyType }, new Expression[] { constantParam, propertyParam }); + + case CompareEnum.NotIn: + return Expression.Not(Expression.Call(typeof(Enumerable), "Contains", new Type[] { realPropertyType }, new Expression[] { constantParam, propertyParam })); + + default: + return Expression.Equal(propertyParam, constantParam); + } + } + + public static Expression> BuildAndAlsoLambda(IEnumerable conditions) + { + if (conditions == null || !conditions.Any()) + return x => true; + + var parameter = Expression.Parameter(typeof(T), "x"); + var simpleExps = conditions + .ToList() + .Select(c => GetExpression(parameter, c)) + .ToList(); + + var exp = simpleExps.Aggregate(null, (left, right) => + left == null ? right : Expression.AndAlso(left, right)); + return Expression.Lambda>(exp, parameter); + } + + public static Expression> BuildOrElseLambda(IEnumerable conditions) + { + if (conditions == null || !conditions.Any()) + return x => true; + + var parameter = Expression.Parameter(typeof(T), "x"); + var simpleExps = conditions + .ToList() + .Select(c => GetExpression(parameter, c)) + .ToList(); + + var exp = simpleExps.Aggregate(null, (left, right) => + left == null ? right : Expression.OrElse(left, right)); + return Expression.Lambda>(exp, parameter); + } } /// - /// Linq表达式实体属性标识 + /// 查询比较符枚举 /// - [AttributeUsage(AttributeTargets.Property)] - public class LinqExpressionXAttribute : Attribute + public enum CompareEnum + { + Equals = 1, + NotEquals = 2, + LessThan = 3, + LessThanOrEquals = 4, + GreaterThan = 5, + GreaterThanOrEquals = 6, + In = 7, + NotIn = 8, + Contains = 9, + NotContains = 10, + StartsWith = 11, + EndsWith = 12 + } + + [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] + public class QueryCompareAttribute : Attribute { /// - /// 属性名称 + /// 属性名 /// - public string Name { get; set; } + public string FieldName { get; set; } /// - /// 操作符 + /// 表达式拼接运算符号 /// - public Operation Operation { get; set; } + public CompareEnum Compare = CompareEnum.Equals; + + /// + /// 值 + /// + public object Value { get; set; } /// /// 是否忽略该属性 /// public bool IsIgnore { get; set; } } - - /// - /// 操作 - /// - public enum Operation - { - GreaterThan, - LessThan, - GreaterThanOrEqual, - LessThanOrEqual, - NotEqual, - Equal, - Like, - In - } } \ No newline at end of file