类型’System.Int32’的表达式不能用于方法’Boolean Equals(System.Object)’的’System.Object’类型的参数

我有一个常见的网格视图列筛选器方法,使用ColumnName和SearchText明智地筛选网格视图记录。 这里当我在nullable int datacolumn上运行时,从这个方法抛出错误,如:

类型’System.Int32’的表达式不能用于方法’Boolean Equals(System.Object)’的’System.Object’类型的参数

我的方法代码是:

public static IQueryable FilterForColumn(this IQueryable queryable, string colName, string searchText) { if (colName != null && searchText != null) { var parameter = Expression.Parameter(typeof(T), "m"); var propertyExpression = Expression.Property(parameter, colName); System.Linq.Expressions.ConstantExpression searchExpression = null; System.Reflection.MethodInfo containsMethod = null; // this must be of type Expression to accept different type of expressions // ie BinaryExpression, MethodCallExpression, ... System.Linq.Expressions.Expression body = null; Expression ex1 = null; Expression ex2 = null; switch (colName) { case "JobID": case "status_id": Int32 _int = Convert.ToInt32(searchText); searchExpression = Expression.Constant(_int); containsMethod = typeof(Int32).GetMethod("Equals", new[] { typeof(Int32) }); body = Expression.Call(propertyExpression, containsMethod, searchExpression); break; case "group_id": Int32? _int1 = Convert.ToInt32(searchText); searchExpression = Expression.Constant(_int1); containsMethod = typeof(Int32?).GetMethod("Equals", new[] { typeof(Int32?) }); //Error throws from this line body = Expression.Call(propertyExpression, containsMethod, searchExpression); break; case "FileSize": case "TotalFileSize": Int64? _int2 = Convert.ToInt64(searchText); searchExpression = Expression.Constant(_int2); containsMethod = typeof(Int64?).GetMethod("Equals", new[] { typeof(Int64?) }); body = Expression.Call(propertyExpression, containsMethod, searchExpression); break; // section for DateTime? properties case "PublishDate": case "Birth_date": case "Anniversary_date": case "Profile_Updated_datetime": case "CompletedOn": DateTime currentDate = DateTime.ParseExact(searchText, "dd/MM/yyyy", null); DateTime nextDate = currentDate.AddDays(1); ex1 = Expression.GreaterThanOrEqual(propertyExpression, Expression.Constant(currentDate, typeof(DateTime?))); ex2 = Expression.LessThan(propertyExpression, Expression.Constant(nextDate, typeof(DateTime?))); body = Expression.AndAlso(ex1, ex2); break; // section for DateTime properties case "Created_datetime": case "Reminder_Date": case "News_date": case "thought_date": case "SubscriptionDateTime": case "Register_datetime": case "CreatedOn": DateTime currentDate1 = DateTime.ParseExact(searchText, "dd/MM/yyyy", null); DateTime nextDate1 = currentDate1.AddDays(1); ex1 = Expression.GreaterThanOrEqual(propertyExpression, Expression.Constant(currentDate1)); ex2 = Expression.LessThan(propertyExpression, Expression.Constant(nextDate1)); body = Expression.AndAlso(ex1, ex2); break; default: searchExpression = Expression.Constant(searchText); containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) }); body = Expression.Call(propertyExpression, containsMethod, searchExpression); break; } var predicate = Expression.Lambda<Func>(body, new[] { parameter }); return queryable.Where(predicate); } else { return queryable; } } 

这是我解雇的问题:

 var query = Helper.GetUsers().Where(u => u.Id != user_id).OrderByDescending(u => u.Register_datetime).Select(u => new { Id = u.Id, Name = u.First_name + " " + u.Last_name, IsActive = u.IsActive, IsVerified = u.IsVerified, Username = u.Username, password = u.password, Birth_date = u.Birth_date, Anniversary_date = u.Anniversary_date, status_id = u.status_id, group_id = u.group_id, Profile_Updated_datetime = u.Profile_Updated_datetime, Register_datetime = u.Register_datetime }).FilterForColumn(ColumnName, SearchText).ToList(); 

这里我包含了我的query.GetType()。ToString()结果,以便更好地理解我对其进行操作的列类型。

 System.Collections.Generic.List`1[f__AnonymousType0`12[System.Int32,System.String,System.Boolean,System.Boolean,System.String,System.String,System.Nullable`1[System.DateTime],System.Nullable`1[System.DateTime],System.Int32,System.Nullable`1[System.Int32],System.Nullable`1[System.DateTime],System.DateTime]] 

编辑

在这个问题中找到了解决方案。 在调用Equals(object)方法之前,需要将表达式转换为Object

 var converted = Expression.Convert(searchExpression, typeof(object)); body = Expression.Call(propertyExpression, containsMethod, converted); 

Nicodemus13建议首先将searchExpression的类型显式设置为Object应该有效。

原版的

我还没有找到问题,但我使用Linqpad在SSCCE中重现了这个问题:

 void Main() { var myInstance = new myClass(); var equalsMethod = typeof(Int32?).GetMethod("Equals", new[] { typeof(Int32?) }); int? nullableInt = 1; var nullableIntExpr = System.Linq.Expressions.Expression.Constant(nullableInt); var myInstanceExpr = System.Linq.Expressions.Expression.Constant(myInstance); var propertyExpr = System.Linq.Expressions.Expression.Property(myInstanceExpr, "MyProperty"); var result = Expression.Call(propertyExpr,equalsMethod,nullableIntExpr); // This line throws the exception. Console.WriteLine(result); } class myClass{public int? MyProperty{get;set;}} 

这一行:

 containsMethod = typeof(Int32?).GetMethod("Equals", new[] { typeof(Int32?) }); 

返回方法Int32?.Equals (Object other)MethodInfo Int32?.Equals (Object other) 。 请注意,参数类型是object ,而不是您期望的Int32 (或Int32? )。

原因是typeof(Int32?)System.Nullable ,它只有Equals(object)方法。

在LinqPad中玩这个,我认为问题在于:

searchExpression = Expression.Constant(_int1);

你打电话的时候:

containsMethod = typeof(Int32?).GetMethod("Equals", new[] { typeof(Int32?) });

你试图调用的Equals方法是object.Equals(object) ,编译器告诉你int?类型int? 不是方法所期望的类型object

最简单的修复(虽然我不确定整个代码是否可行,但这个特殊错误会消失)是更改您调用的Expression.Constant的重载,指定Equals期望的类型:

searchExpression = Expression.Constant(_int1, typeof(object));

这将编译 – 但是,有一些事情需要注意。

  1. 你原来的Expression.Constant(_int1)导致一个ConstantExpressionType int不是int? 。 如果需要,您需要指定可空类型( Expression.Constant(_int1, typeof(int?)) )。 但是,如上所述,您还需要将其强制转换为object

  2. 指定containsMethod = typeof(Int32?).GetMethod("Equals", new[] { typeof(Int32?) }); 无论如何都不应该工作,因为没有这样的方法int?.Equals(int?)Equals方法是System.Object类上的方法的重写,它接受一个object参数并且是问题的根。 你也可以使用: typeof(object).GetMethod("Equals", new[] { typeof(object) }); 因为这是正确的声明。

正如我所说,它应该与object编译,代码是否符合你的期望,我不确定,但我想是的。 我期待看到它是否有效:)