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

0

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?

c#
reflection
.net-core
ambiguous-call
asked on Stack Overflow Sep 7, 2019 by si2030 • edited Sep 7, 2019 by Peter Duniho

1 Answer

4

While your question didn't say so specifically, it was inferred from the provided stack trace that you are running the code in the .NET Core environment.

Note that it was not possible to reproduce this error on the .NET Framework environment.

When testing in .Net Core the error was occurring on this line

private static MethodInfo containsMethod = typeof(string).GetMethod("Contains");  

Note the lack of an argument type to narrow the method match.

By providing an argument type like

private static MethodInfo containsMethod = 
    typeof (string).GetMethod("Contains", new Type[]{typeof (string)});

The error was resolved and the code behaved as expected.

.Net Fiddle of working code

answered on Stack Overflow Sep 7, 2019 by Nkosi • edited Jun 20, 2020 by Community

User contributions licensed under CC BY-SA 3.0