Я слежу за pashov.net и, в частности, за его подходом к фильтрации путем создания динамического Linq. выражения.
Я реализовал его, и он работал, но поиск строки чувствителен к регистру. В настоящее время у него нет параметра IndexOf StringComparison.OrdinalIgnoreCase, поэтому я попытался добавить его.
Я получаю сообщение об ошибке, как только он достигает той части кода, где он пытается запустить на нем лямбда-вызов ... return Expression.Lambda<Func<T, bool>>(exp, param);
Возникли проблемы с преобразованием из int32 в bool.
System.ArgumentException
HResult=0x80070057
Message=Expression of type 'System.Int32' cannot be used for return type 'System.Boolean'
Source=System.Linq.Expressions
StackTrace:
at System.Linq.Expressions.Expression.ValidateLambdaArgs(Type delegateType, Expression& body, ReadOnlyCollection`1 parameters, String paramName)
at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, String name, Boolean tailCall, IEnumerable`1 parameters)
at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, Boolean tailCall, IEnumerable`1 parameters)
at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, ParameterExpression[] parameters)
at JobsLedger.API.ControllerServices.Shared.OrderAndFIlterHelpers.DynamicFilteringHelper.ConstructAndExpressionTree[T](List`1 filters) in C:\AURELIA\1.0 - JobsLedgerSPA -ASPNET CORE 3.0\JobsLedger.API\ControllerServices\Shared\OrderAndFIlterHelpers\DynamicFilteringHelper.cs:line 48
at JobsLedger.API.ControllerServices.Shared.ODataFilterAndSort.ParginatedFilteredSorted[T](IQueryable`1 source, String query) in C:\AURELIA\1.0 - JobsLedgerSPA -ASPNET CORE 3.0\JobsLedger.API\ControllerServices\Shared\OrderAndFIlterHelpers\ODataFilterAndSort.cs:line 41
at JobsLedger.API.ControllerServices.API.App.ClientServices.ClientServices.GetPaginatedClients(String query) in C:\AURELIA\1.0 - JobsLedgerSPA -ASPNET CORE 3.0\JobsLedger.API\ControllerServices\API\App\ClientServices\ClientServices.cs:line 65
at JobsLedger.API.Controllers.API.App.ClientController.Index(String query) in C:\AURELIA\1.0 - JobsLedgerSPA -ASPNET CORE 3.0\JobsLedger.API\Controllers\API\App\ClientController.cs:line 28
at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
Я провел несколько исследований, и мне было предложено преобразовать его с помощью .Convert
, но это не сработало, так как преобразование из int32 в bool.
вот код.
public static Expression<Func<T, bool>> ConstructAndExpressionTree<T>(List<ExpressionFilter> filters) {
if (filters.Count == 0)
return null;
ParameterExpression param = Expression.Parameter(typeof(T), "t");
Expression exp = null;
if (filters.Count == 1) {
exp = ExpressionRetriever.GetExpression<T>(param, filters[0]);
}
else {
exp = ExpressionRetriever.GetExpression<T>(param, filters[0]);
for (int i = 1; i < filters.Count; i++) {
exp = Expression.And(exp, ExpressionRetriever.GetExpression<T>(param, filters[i]));
}
}
return Expression.Lambda<Func<T, bool>>(exp, param); //.. FAILS HERE
}
public static class ExpressionRetriever {
private static MethodInfo containsMethod = typeof(string).GetMethod("Contains");
private static MethodInfo startsWithMethod = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
private static MethodInfo endsWithMethod = typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) });
public static Expression GetExpression<T>(ParameterExpression param, ExpressionFilter filter) {
MemberExpression member = Expression.Property(param, filter.PropertyName);
ConstantExpression constant = Expression.Constant(filter.Value);
switch (filter.Comparison) {
case Comparison.Equal:
return Expression.Equal(member, constant);
case Comparison.GreaterThan:
return Expression.GreaterThan(member, constant);
case Comparison.GreaterThanOrEqual:
return Expression.GreaterThanOrEqual(member, constant);
case Comparison.LessThan:
return Expression.LessThan(member, constant);
case Comparison.LessThanOrEqual:
return Expression.LessThanOrEqual(member, constant);
case Comparison.NotEqual:
return Expression.NotEqual(member, constant);
case Comparison.Contains:
return Expression.Call(member, containsMethod, constant);
case Comparison.StartsWith:
return Expression.Call(member, startsWithMethod, constant);
case Comparison.IndexOf:
var test = Expression.Call(member, "IndexOf", null, Expression.Constant(filter.Value, typeof(string)), Expression.Constant(StringComparison.InvariantCultureIgnoreCase));
return test;
//return Expression.Convert(test, typeof(bool));
case Comparison.EndsWith:
return Expression.Call(member, endsWithMethod, constant);
default:
return null;
}
}
}
Было бы неплохо, если бы я мог вставить код, который не требовал создания вызова, как это сделал я. Есть ли способ реализовать это как метод и т. Д. В соответствии с другими параметрами строки, или это способ, которым я пробовал единственный способ, учитывая, что мне нужен дополнительный параметр ..
т.е. как я могу реализовать опцию IndexOf и вернуть bool?
IndexOf
возвращает число (то есть индекс), а не логическое значение. Я не уверен, когда вы ожидаете, что это вернет true, а когда - false, но я думаю, что вы, возможно, пытаетесь повторно реализоватьContains
под другим именем - person Andrew Williamson   schedule 07.09.2019