C# 使用动态 lambda 但在选择要使用的方法时得到不明确的匹配
C# Using dynamic lambda but getting an ambiguous match when selecting a method to use
根据 Pashov 的博客 post,我有以下用于 select 在过滤器选项之间切换的静态方法。
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;
}
}
}
一旦它到达行 return Expression.Call(member, startsWithMethod, constant);
就会抛出以下错误:
> 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.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.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.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.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.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.
如果我注释掉 private static MethodInfo containsMethod
和 private static MethodInfo endsWithMethod
它现在可以工作了。
我发现这个 post's answer (same kind of problem) that said to use this 过载,但它已经这样做了。
我怎样才能避免这种情况,以便它可以 select 在不同的方法之间看到不明确的选择?
虽然您的问题没有具体说明,但从提供的堆栈跟踪中推断您是 运行 .NET Core 环境中的代码。
请注意,无法在 .NET Framework 环境中重现此错误。
在 .Net Core 中测试时,此行出现错误
private static MethodInfo containsMethod = typeof(string).GetMethod("Contains");
请注意缺少用于缩小方法匹配范围的参数类型。
通过提供像
这样的参数类型
private static MethodInfo containsMethod =
typeof (string).GetMethod("Contains", new Type[]{typeof (string)});
错误已解决,代码按预期运行。
.Net Fiddle of working code
根据 Pashov 的博客 post,我有以下用于 select 在过滤器选项之间切换的静态方法。
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;
}
}
}
一旦它到达行 return Expression.Call(member, startsWithMethod, constant);
就会抛出以下错误:
> 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.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.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.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.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.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.
如果我注释掉 private static MethodInfo containsMethod
和 private static MethodInfo endsWithMethod
它现在可以工作了。
我发现这个 post's answer (same kind of problem) that said to use this 过载,但它已经这样做了。
我怎样才能避免这种情况,以便它可以 select 在不同的方法之间看到不明确的选择?
虽然您的问题没有具体说明,但从提供的堆栈跟踪中推断您是 运行 .NET Core 环境中的代码。
请注意,无法在 .NET Framework 环境中重现此错误。
在 .Net Core 中测试时,此行出现错误
private static MethodInfo containsMethod = typeof(string).GetMethod("Contains");
请注意缺少用于缩小方法匹配范围的参数类型。
通过提供像
这样的参数类型private static MethodInfo containsMethod =
typeof (string).GetMethod("Contains", new Type[]{typeof (string)});
错误已解决,代码按预期运行。