Expression of type 'System.Int32' cannot be used for parameter of type 'System.Object' of method 'Boolean Equals(System.Object)'
.net, c#, linq, linq-expressions
Solution
EDIT
Found the solution in this question. You need to convert the expression to `Object` before calling the `Equals(object)`method:
var converted = Expression.Convert(searchExpression, typeof(object));
body = Expression.Call(propertyExpression, containsMethod, converted);
Nicodemus13's suggestion of explicitly setting `searchExpression`'s type to `Object` in the first place should work, too.
Original
I haven't found the issue yet, but I have reproduced the problem in a SSCCE using Linqpad:
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;}}
This line:
containsMethod = typeof(Int32?).GetMethod("Equals", new[] { typeof(Int32?) });
returns a `MethodInfo` for the method `Int32?.Equals (Object other)`. Notice the parameter type is `object`, not `Int32` (or `Int32?`) as you might expect.
The reason is `typeof(Int32?)` is `System.Nullable<Int32>`, which only has the `Equals(object)` method.
Problem
i have one common grid view column filter method that filter grid view record with ColumnName and SearchText wise. here when i operate on nullable int datacolumn there is error thrown from this method like : Expression of type 'System.Int32' cannot be used for parameter of type 'System.Object' of method 'Boolean Equals(System.Object)' my method code is : ``` public static IQueryable<T> FilterForColumn<T>(this IQueryable<T> 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 // i.e. 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<T, bool>>(body, new[] { parameter }); return queryable.Where(predicate); } else { return queryable; } } ``` here is my query that i fired : ``` 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(); ``` here i include my query.GetType().ToString() result for better understanding types of columns that i operate on it. ``` 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]] ```