防爆$ P $类型'System.Int32的“的pssion不能用于类型参数'System.Object的'法'布尔等于(System.Object的)'类型

2023-09-05 03:30:17 作者:看透卜说透 ∞

我有一个共同的网格视图列过滤器的方法,与的ColumnName和SearchText明智的过滤器网格视图记录。这里的时候,我可为空INT DataColumn的操作存在误差从此方法抛出这样的:

 防爆$类型'System.Int32的的对$ pssion不能用于类型参数'System.Object的'法'布尔等于(System.Object的)'
 

我的方法code是:

 公共静态的IQueryable< T> FilterForColumn< T>(这IQueryable的< T>可查询字符串COLNAME,串searchText)
        {
            如果(COLNAME = NULL和放大器;!&安培;!searchText = NULL)
            {
                VAR参数=前pression.Parameter(typeof运算(T),M);
                VAR propertyEx pression =前pression.Property(参数COLNAME);
                System.Linq.Ex pressions.ConstantEx pression searchEx pression = NULL;
                System.Reflection.MethodInfo containsMethod = NULL;
                //这必须是防爆型$ P ​​$ pssion接受不同类型的EX pressions
                //即BinaryEx pression,MethodCallEx pression,...
                System.Linq.Ex pressions.Ex pression体= NULL;
                防爆pression EX1 = NULL;
                防爆pression EX2 = NULL;
                开关(COLNAME)
                {
                    案作业ID:
                    案status_id:
                        INT32 _INT = Convert.ToInt32(searchText);
                        sea​​rchEx pression =前pression.Constant(_INT);
                        containsMethod = typeof运算(Int32)已.GetMethod(等于,新的[] {typeof运算(Int32)已});
                        身体=前pression.Call(propertyEx pression,containsMethod,searchEx pression);
                        打破;
                    案GROUP_ID:
                        INT32? _int1 = Convert.ToInt32(searchText);
                        sea​​rchEx pression =前pression.Constant(_int1);
                        。containsMethod = typeof运算(?Int32)在GetMethod的(等于,新的[] {typeof运算(Int32)已?});
                        //错误,从该行抛出
                        身体=前pression.Call(propertyEx pression,containsMethod,searchEx pression);


打破;
                    案文件大小:
                    案TotalFileSize:
                        Int64的? _int2 = Convert.ToInt64(searchText);
                        sea​​rchEx pression =前pression.Constant(_int2);
                        。containsMethod = typeof运算(?的Int64)GetMethod的(等于,新的[] {typeof运算(Int64的)?});
                        身体=前pression.Call(propertyEx pression,containsMethod,searchEx pression);
                        打破;
                    //节日期时间?性能
                    案PublishDate:
                    案Birth_date:
                    案Anniversary_date:
                    案Profile_Updated_datetime:
                    案CompletedOn:
                        日期时间的currentdate = DateTime.ParseExact(searchText,DD / MM / YYYY,NULL);
                        日期时间nextDate = currentDate.AddDays(1);
                        EX1 =前pression.GreaterThanOrEqual(propertyEx pression,防爆pression.Constant(的currentdate的typeof(DateTime的)));
                        EX2 =前pression.LessThan(propertyEx pression,防爆pression.Constant(nextDate的typeof(DateTime的)));
                        身体=前pression.AndAlso(EX1,EX2);
                        打破;
                    //节日期时间属性
                    案Created_datetime:
                    案Reminder_Date:
                    案News_date:
                    案thought_date:
                    案SubscriptionDateTime:
                    案Register_datetime:
                    案CreatedOn:
                        日期时间currentDate1 = DateTime.ParseExact(searchText,DD / MM / YYYY,NULL);
                        日期时间nextDate1 = currentDate1.AddDays(1);
                        EX1 =前pression.GreaterThanOrEqual(propertyEx pression,防爆pression.Constant(currentDate1));
                        EX2 =前pression.LessThan(propertyEx pression,防爆pression.Constant(nextDate1));
                        身体=前pression.AndAlso(EX1,EX2);
                        打破;
                    默认:
                        sea​​rchEx pression =前pression.Constant(searchText);
                        containsMethod = typeof运算(字符串).GetMethod(包含,新的[] {typeof运算(字符串)});
                        身体=前pression.Call(propertyEx pression,containsMethod,searchEx pression);
                        打破;
                }
                VAR predicate =前pression.Lambda< Func键< T,布尔>>(身体,新的[] {参数});
                返回queryable.Where(predicate);
            }
            其他
            {
                返回可查询;
            }
        }
 

这是我的查询,我解雇了:

  VAR的查询= Helper.GetUsers()式(U =>!u.Id = USER_ID)。.OrderByDescending(U => u.Register_datetime)。选择(U = >新建
                      {
                          n = u.Id,
                          名称= u.First_name ++ u.Last_name,
                          IsActive = u.IsActive,
                          IsVerified = u.IsVerified,
                          用户名= u.Username,
                          密码= 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()。
 
C97 Diverse System Trailer

在这里,我有我的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]]

解决方案

修改

在找到this问题。您需要调用等于之前(对象)方法转换前pression到对象

  VAR转换=前pression.Convert(searchEx pression的typeof(对象));
身体=前pression.Call(propertyEx pression,containsMethod,转换);
 

倪codemus13 的明确设置的建议 searchEx pression 的类型在首位对象应该工作了。

我还没有发现这个问题,但我已经转载使用Linqpad在SSCCE问题:

 无效的主要()
{
    VAR将myInstance =新MyClass的();
    。VAR equalsMethod = typeof运算(?Int32)在GetMethod的(等于,新的[] {typeof运算(Int32)已?});
    诠释? nullableInt = 1;
    VAR nullableIntExpr = System.Linq.Ex pressions.Ex pression.Constant(nullableInt);
    VAR myInstanceExpr = System.Linq.Ex pressions.Ex pression.Constant(将myInstance);
    VAR propertyExpr = System.Linq.Ex pressions.Ex pression.Property(myInstanceExpr,myProperty的);
    VAR的结果=前pression.Call(propertyExpr,equalsMethod,nullableIntExpr); //这行抛出异常。
    Console.WriteLine(结果);
}

MyClass类{公众诠释? {myProperty的获取;设置;}}
 

这行:

  containsMethod = typeof运算(?Int32)在GetMethod的(等于,新的[] {typeof运算(Int32)已?})。
 

返回的MethodInfo 的方法的Int32?.Equals(对象等)。注意参数类型为对象,不是的Int32 (或的Int32?)如你所期望的。

原因是的typeof(的Int32?) System.Nullable&LT;的Int32&GT; ,其不仅具有等于(对象)方法。

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]]

解决方案

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.