我们想为实体框架创建一个linq表达式,如下所示:
//assume numericList is List<int>
entity => numericList.Contain(entity.Id);
我们按照以下方式做到了:
// propertType = {Name = "Int32" FullName = "System.Int32"}
// propertyInfo = {Int32 Serial}
// parameterExpression = {entity}
MemberExpression leftSile = Expression.Property(parameterExpression, propertyInfo);
Type listType = typeof (ICollection<>);
Type numbericGenericType = listType.MakeGenericType(propertType);
var valueObject = JsonConvert.DeserializeObject("[1,2,3,4,5]", numbericGenericType);
MethodInfo iListMethodInfo = numbericGenericType.GetMethod("Contains", new[] { propertType });
List<Expression> expressions = new List<Expression>();
foreach (object item in valueObject as ICollection)
expressions.Add(Expression.Constant(item));
result = Expression.Call(leftSile, iListMethodInfo, expressions); // Exception
没关系,但发生了以下异常:
An unhandled exception of type 'System.ArgumentException' occurred in System.Core.dll
Additional information: Method 'Boolean Contains(Int32)' declared on type 'System.Collections.Generic.ICollection`1[System.Int32]' cannot be called with instance of type 'System.Int32'
我们怎么做?
我们的代码怎么了?
答案 0 :(得分:1)
您的代码不正确,因为它尝试构建此调用:
entity.Id.Contains(1, 2, 3, 4, 5)
Expression.Call
的第一个参数表示调用方法的对象。它应该是表示集合的表达式,而不是leftSide
表达式entity.Id
。最重要的是,参数的数量不匹配,但C#没有报告,因为左侧是错误的。
此外,您没有表示集合的表达式,您有一个包含大量表达式的集合。您可以将此类集合构造为常量表达式,如下所示:
Expression collection = Expression.Constant(valueObject); // This replaces the loop
现在你可以做一个这样的表达式:
result = Expression.Call(collection, iListMethodInfo, leftSile);