vendredi 6 septembre 2019

C# Using dynamic lambda but getting an ambiguous match when selecting a method to use

I have the following static method for selecting between filter options as per a blog post by Pashov.

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.EndsWith:  
                return Expression.Call(member, endsWithMethod, constant);  
            default:  
                return null;  
        }  
    }  
}

Once it hits the line return Expression.Call(member, startsWithMethod, constant); it throws the following error:

> System.TypeInitializationException
  HResult=0x80131534
  Message=The type initializer for 'ExpressionRetriever' threw an exception.
  Source=JobsLedger.API
  StackTrace:
   at JobsLedger.API.ControllerServices.Shared.OrderAndFIlterHelpers.DynamicFilteringHelper.ExpressionRetriever.GetExpression[T](ParameterExpression param, ExpressionFilter filter) in C:\AURELIA\1.0 - JobsLedgerSPA -ASPNET CORE 3.0\JobsLedger.API\ControllerServices\Shared\OrderAndFIlterHelpers\DynamicFilteringHelper.cs:line 84
   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 39
   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()
> 
> Inner Exception 1: AmbiguousMatchException: Ambiguous match found.

If I comment out the private static MethodInfo containsMethod and private static MethodInfo endsWithMethod It now works.

I found this post's answer (same kind of problem) that said to use this overload but its already doing that.

How can I avoid this so that it can select between the different methods without seeing ambiguous choices?





Aucun commentaire:

Enregistrer un commentaire