在集合上应用动态构建的表达式会引发异常

时间:2015-06-28 15:23:14

标签: c# .net lambda expression expression-trees

我有以下课程:

public class Order
{
    public string Code { get; set; } 
}

我有一个订单列表,List<Order>表达式类型以及我应用过滤器时的this

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 =&gt; (True AndAlso x.Code.Contains(&#34;&#39; af&#39;&#34;))}

DebugView: .Lambda#Lambda1(Artemis.Sample.Order $ x){     真实&amp;&amp; .Call($ x.Code).Contains(&#34;&#39; af&#39;&#34;) }

并使用类似于:

的扩展方法
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可能有什么问题?

1 个答案:

答案 0 :(得分:0)

我将您发布的确切代码放在您的问题和GitHub链接中。代码在我的示例中正常工作(尽管它不处理null的{​​{1}}值。我尝试了框架版本Order.Code4.04.54.5.1.,并且每个版本都运行良好。

我相信您已对GitHub页面中发布的代码进行了修改,导致此错误。这意味着我无法重现您的问题。

我认为您不需要在4.5.2实现中使用动态调用。这是因为您在编译时似乎知道WhereByFilter,在这种情况下,没有理由破坏类型安全性。这可能会澄清你得到的错误:

T