类型’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));
这将编译 – 但是,有一些事情需要注意。
-
你原来的
Expression.Constant(_int1)
导致一个ConstantExpression
,Type
int
不是int?
。 如果需要,您需要指定可空类型(Expression.Constant(_int1, typeof(int?))
)。 但是,如上所述,您还需要将其强制转换为object
。 -
指定
containsMethod = typeof(Int32?).GetMethod("Equals", new[] { typeof(Int32?) });
无论如何都不应该工作,因为没有这样的方法int?.Equals(int?)
,Equals
方法是System.Object
类上的方法的重写,它接受一个object
参数并且是问题的根。 你也可以使用:typeof(object).GetMethod("Equals", new[] { typeof(object) });
因为这是正确的声明。
正如我所说,它应该与object
编译,代码是否符合你的期望,我不确定,但我想是的。 我期待看到它是否有效:)