Выражение типа ' System.Int32 'нельзя использовать для параметра типа' System.Объект "метода" Boolean Equals (System.Объект')

у меня есть один общий метод фильтра столбцов представления сетки, который фильтрует запись представления сетки с помощью ColumnName и SearchText. здесь, когда я работаю с nullable int datacolumn, из этого метода возникает ошибка:

выражение типа ' System.Int32 'нельзя использовать для параметра типа' System.Объект "метода" Boolean Equals (System.Объект)'

мой метод код :

 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;
    }
}

вот мой запрос, который я уволен :

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();

здесь я включаю свой запрос.метод 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]]

2 ответов


редактировать

нашел решение в этот вопрос. Вам нужно преобразовать выражение в Object перед вызовом Equals(object)способ:

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

Nicodemus13предложение явно установить searchExpression'ы типа Object в первую очередь должен работать тоже.

Оригинал

я еще не нашел проблему, но я воспроизвел проблему в SSCCE, используя Помощью 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;}}

эта строка:

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

возвращает MethodInfo для метода Int32?.Equals (Object other). Обратите внимание, что тип параметра object, а не Int32 (или Int32?) как и следовало ожидать.

причина typeof(Int32?) и System.Nullable<Int32>, которая имеет Equals(object) метод.


играя с этим в LinqPad, я думаю, что проблема вокруг:

searchExpression = Expression.Constant(_int1);

когда вы называете:

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

на Equals метод, который вы пытаетесь назвать это object.Equals(object) и компилятор говорит вам, что типа int? не типа object что метод ожидает.

самое простое исправление (хотя я не уверен, что общий код будет работать, хотя эта конкретная ошибка исчезнет) - это изменить перегрузка Expression.Constant что вы вызываете к одному, который указывает тип, который Equals ожидает:

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

это компиляции, однако, есть несколько вещей, чтобы отметить.

  1. ваш оригинальный Expression.Constant(_int1) результаты ConstantExpression С Type int не int?. Вам нужно будет указать тип nullable, если вам это нужно (Expression.Constant(_int1, typeof(int?))). Тем не менее, вам нужно будет бросить его в object в любом случае, как выше.

  2. задание containsMethod = typeof(Int32?).GetMethod("Equals", new[] { typeof(Int32?) }); не должен работать в любом случае, так как нет такого метода int?.Equals(int?), the Equals метод переопределить метод на System.Object класс, который берет