From 80534f81af15a7ac589207dc191dadc48c794aaf Mon Sep 17 00:00:00 2001 From: NazarovMikhail Date: Fri, 12 Jan 2024 11:06:18 +0500 Subject: [PATCH] Add supported types dictionary for searching. --- .../Extensions/QueryableExtensions.cs | 82 +++++++++++++------ 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/src/Monq.Core.Paging/Extensions/QueryableExtensions.cs b/src/Monq.Core.Paging/Extensions/QueryableExtensions.cs index 39d2ab5..6b96f23 100644 --- a/src/Monq.Core.Paging/Extensions/QueryableExtensions.cs +++ b/src/Monq.Core.Paging/Extensions/QueryableExtensions.cs @@ -3,11 +3,29 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using System.Reflection; namespace Monq.Core.Paging.Extensions { public static class QueryableExtensions { + // if it needs checking search value - method TryParse else - null + static readonly Dictionary _supportedTypes = new() + { + [typeof(int)] = typeof(int).GetMethod( + nameof(int.TryParse), + new Type[] { typeof(string), typeof(int).MakeByRefType() })!, + [typeof(long)] = typeof(int).GetMethod( + nameof(int.TryParse), + new Type[] { typeof(string), typeof(int).MakeByRefType() })!, + [typeof(Guid)] = null, + }; + + static readonly MethodInfo _methodContains = typeof(string).GetMethod(nameof(string.Contains), new[] { typeof(string) })!; + static readonly MethodInfo _methodToString = typeof(object).GetMethod(nameof(ToString))!; + static readonly MethodInfo _methodToLower = typeof(string).GetMethod(nameof(string.ToLower), Type.EmptyTypes)!; + static readonly MethodInfo _methodIsNullOrEmpty = typeof(string).GetMethod(nameof(string.IsNullOrEmpty), new[] { typeof(string) })!; + /// /// Orderings the by. /// @@ -56,49 +74,32 @@ public static IQueryable OrderByProperty(this IQueryable p.Property.PropertyType == typeof(string)).ToList(); - + if (!props.Any()) return null; var parameter = Expression.Parameter(typeof(TSource), "t"); - var methodContains = typeof(string).GetMethod(nameof(string.Contains), new[] { typeof(string) }); - var methodToLower = typeof(string).GetMethod(nameof(string.ToLower), Type.EmptyTypes); - var methodToString = typeof(object).GetMethod(nameof(ToString)); - var methodIsNullOrEmpty = typeof(string).GetMethod(nameof(string.IsNullOrEmpty), new[] { typeof(string) }); - var value = Expression.Constant(search.ToLower(), typeof(string)); - var expList = new List(); foreach (var (fullName, _) in stringProperties) { var expMember = parameter.GetPropertyExpressionUnSafe(fullName); - var extIsNullOrEmpty = Expression.Not(Expression.Call(methodIsNullOrEmpty, expMember.AddNullConditions())); + var extIsNullOrEmpty = Expression.Not(Expression.Call(_methodIsNullOrEmpty, expMember.AddNullConditions())); - var expLower = Expression.Call(expMember, methodToLower); - var expContains = Expression.Call(expLower, methodContains, value); + var expLower = Expression.Call(expMember, _methodToLower); + var expContains = Expression.Call(expLower, _methodContains, value); var extAnd = Expression.AndAlso(extIsNullOrEmpty, expContains); expList.Add(extAnd); } - if (long.TryParse(search, out _) || Guid.TryParse(search, out _)) - { - var valueProperties = props.Where(p => - p.Property.PropertyType == typeof(int) - || p.Property.PropertyType == typeof(long) - || p.Property.PropertyType == typeof(Guid)); - - var expression = Expression.Constant(true); - foreach (var (fullName, _) in valueProperties) - { - var expMember = parameter.GetPropertyExpression(fullName); - var ext = Expression.Call(expMember, methodToString); - var extContains = Expression.Call(ext, methodContains, value); - var extAnd = Expression.Equal(extContains, expression); - expList.Add(extAnd); - } - } + var valueExpressions = FormExpressionsForSupportedTypes( + props, + parameter, + search); + + expList.AddRange(valueExpressions); if (expList.Count == 0) return null; @@ -106,5 +107,32 @@ public static IQueryable OrderByProperty(this IQueryable>(body, parameter); } + + private static IEnumerable FormExpressionsForSupportedTypes( + IEnumerable<(string FullName, PropertyInfo Property)> targetProps, + ParameterExpression parameter, + string searchValue) + { + var result = new List(); + var valueExpr = Expression.Constant(searchValue.ToLower(), typeof(string)); + var expression = Expression.Constant(true); + + foreach (var (fullName, prop) in targetProps) + { + if (!_supportedTypes.TryGetValue(prop.PropertyType, out var tryParseMethod)) + continue; + + if (tryParseMethod != null + && (bool)tryParseMethod.Invoke(null, new object?[] { searchValue, null })! == false) + continue; + + var expMember = parameter.GetPropertyExpression(fullName); + var ext = Expression.Call(expMember, _methodToString); + var extContains = Expression.Call(ext, _methodContains, valueExpr); + var extAnd = Expression.Equal(extContains, expression); + result.Add(extAnd); + } + return result; + } } } \ No newline at end of file