使用c#中的反射创建数字包含表达式?

时间:2014-11-29 12:29:02

标签: c# linq reflection expression

我们想为实体框架创建一个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'

我们怎么做?
我们的代码怎么了?

1 个答案:

答案 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);