对集合应用动态生成的表达式会引发异常
本文关键字:表达式 异常 集合 应用 动态 | 更新日期: 2023-09-27 18:00:05
我有以下类:
public class Order
{
public string Code { get; set; }
}
我有一个顺序列表,表达式类型的List<Order>
,当我应用这样的过滤器时:
var buildExpressionFilter = ExpressionQuery
.Empty
.WithType(typeof(Order))
.AndContains("Code", "af")
.GetResult();
Expression<Func<Order, bool>> normalFilter = x => x.Code.Contains("af");
var orders = GetOrders();
var result = orders.WhereByFilter(buildExpressionFilter).ToList(); //fails as shown below
var result2 = orders.WhereByFilter(normalFilter ).ToList(); //works ok
buildExpressionFilter具有以下属性:
正文:{x=>(True AndAlso x.Code.Contains("'af'"))}
调试视图:。Lambda#Lambda1(Artemis.Sample.Order$x){真&。调用($x.Code)。包含("'af'")}
并使用一种扩展方法,看起来像:
public static IEnumerable<T> WhereByFilter<T>(this IEnumerable<T> collection, Expression filter)
{
dynamic dynamicFilter = filter;
dynamic function = dynamicFilter.Compile();
dynamic result = Enumerable.Where(collection, function); //CRASHES HERE
return result;
}
我得到以下错误:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderInternalCompilerException : An unexpected exception occurred while binding a dynamic operation
at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.Bind(DynamicMetaObjectBinder payload, IEnumerable`1 parameters, DynamicMetaObject[] args, ref DynamicMetaObject deferredBinding)
at Microsoft.CSharp.RuntimeBinder.BinderHelper.Bind(DynamicMetaObjectBinder action, RuntimeBinder binder, IEnumerable`1 args, IEnumerable`1 arginfos, DynamicMetaObject onBindingError)
at Microsoft.CSharp.RuntimeBinder.CSharpInvokeBinder.FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
at System.Dynamic.InvokeBinder.FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args)
at System.Dynamic.DynamicMetaObject.BindInvoke(InvokeBinder binder, DynamicMetaObject[] args)
at System.Dynamic.InvokeBinder.Bind(DynamicMetaObject target, DynamicMetaObject[] args)
at System.Dynamic.DynamicMetaObjectBinder.Bind(Object[] args, ReadOnlyCollection`1 parameters, LabelTarget returnLabel)
at System.Runtime.CompilerServices.CallSiteBinder.BindCore(CallSite`1 site, Object[] args)
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2<T0,T1>(CallSite site, T0 arg0, T1 arg1)
at Artemis.Common.Collection.CollectionExtensions.WhereByFilter(IEnumerable`1 collection, Expression filter) in CollectionUtils.cs: line 25
很明显,buildExpressionFilter没有正确构造,因为使用常规过滤器进行调用是有效的。
有人知道如何解决这个问题吗?我的buildExpressionFilter可能出了什么问题?
我把你发布的确切代码放在你的问题和GitHub链接中。在我的示例中,代码运行良好(尽管它不处理Order.Code
的null
值)。我尝试了框架版本4.0
、4.5
、4.5.1.
和4.5.2
,它们都运行良好。
我相信你已经对GitHub页面中发布的代码进行了修改,这导致了这个错误。这意味着我没有办法重现你的问题。
我认为您不需要在WhereByFilter
实现中使用动态调用。这是因为您在编译时似乎知道T
,在这种情况下,没有理由破坏类型安全性。这可能会澄清你得到的错误:
public static IEnumerable<T> WhereByFilter<T>(this IEnumerable<T> collection, Expression<Func<T, bool>> filter)
{
var function = filter.Compile();
return collection.Where(function);
}