2014-04-15 13 views
6

Ho un metodo di filtro di colonna di visualizzazione griglia comune che filtra il record di visualizzazione griglia con ColumnName e SearchText saggio. qui quando opero su nullable int DataColumn c'è errore generato da questo metodo come:L'espressione di tipo "System.Int32" non può essere utilizzata per il parametro di tipo "System.Object" del metodo "Boolean Equals (System.Object)"

Expression of type 'System.Int32' cannot be used for parameter of type 'System.Object' of method 'Boolean Equals(System.Object)' 

mio codice metodo è:

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

Ecco la mia domanda che ho sparato:

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

qui includo il mio risultato query.GetType(). ToString() per capire meglio i tipi di colonne su cui lavoro.

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

quale linea è l'eccezione? – thumbmunkeys

+0

dalla riga del corpo del caso group_id. mostra una domanda aggiornata –

risposta

9

EDIT

ha trovato la soluzione in this question. È necessario per convertire l'espressione Object prima di chiamare il metodo Equals(object):

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

Nicodemus13 's suggerimento di impostare in modo esplicito searchExpression' s tipo di Object in primo luogo dovrebbe funzionare, anche.

originale

non ho ancora trovato il problema, ma ho riprodotto il problema in uno SSCCE utilizzando 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;}} 

questa linea: i rendimenti

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

a MethodInfo per il metodo Int32?.Equals (Object other). Si noti che il tipo di parametro è object, non Int32 (o Int32?) come ci si potrebbe aspettare.

La ragione è typeof(Int32?) è System.Nullable<Int32>, che ha solo il metodo Equals(object).

+0

funziona. ma come mai in casi di caso FileSize, TotalFileSize non ho mai riscontrato alcun problema come questo. –

+0

Penso che sia perché quelli in realtà non appaiono nella tua query, quindi l'istruzione 'case' corrispondente non viene mai eseguita. – Rik

+0

Possiamo affrontare problemi come la conversione in oggetto nel caso in cui lavoriamo con Int64 ?. –

2

Giocando intorno con questo in LINQPad, penso che il problema è di circa:

searchExpression = Expression.Constant(_int1);

quando si chiama:

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

Il metodo Equals si sta tentando di chiamata è object.Equals(object) e il compilatore sta dicendo che il tipo int? non è il tipo object che il metodo si aspetta.

La correzione più semplice (anche se non sono sicuro che il codice complesso funzionerà, anche se questo errore particolare andrà via) è di cambiare il sovraccarico del Expression.Constant che si chiama per uno che specifica il tipo che aspetta Equals:

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

Questo sarà di compilazione tuttavia, ci sono alcune cose da notare.

  1. l'originale Expression.Constant(_int1) risultati in un ConstantExpression con Typeint non int?. Dovresti specificare il tipo annullabile, se necessario (Expression.Constant(_int1, typeof(int?))). Tuttavia, dovrai lanciarlo ugualmente su object, come sopra.

  2. Specifica containsMethod = typeof(Int32?).GetMethod("Equals", new[] { typeof(Int32?) }); non dovrebbe funzionare in ogni caso, non c'è tale metodo int?.Equals(int?), il metodo Equals è la sostituzione del metodo sulla classe System.Object che accetta un parametro object ed è la radice del problema. Puoi anche usare: typeof(object).GetMethod("Equals", new[] { typeof(object) }); dato che è la dichiarazione corretta.

Come ho detto, si deve compilare con object, se il codice fa quello che ci si aspetta, non sono sicuro, ma credo di sì. Non vedo l'ora di vedere se funziona :)

+0

grazie per il lavoro di u..it. ma come mai mi chiedo di non aver bisogno di questa tecnica usata per Int64? –

+0

Stai dicendo che (tuo) esattamente lo stesso codice, ma la sostituzione di 'Int32?' Con 'Int64?' Non getta l'eccezione originale? – nicodemus13

+0

non in sostituzione significa che ho già Int64? che sta funzionando bene perché Int32? ottenendo un errore del genere –

Problemi correlati