2014-04-15 16 views
6

Ich habe eine gemeinsame Rasteransicht Spaltenfiltermethode, die Rasteransicht Datensatz mit ColumnName filtern und SearchText weise. hier, wenn ich auf NULL festlegbare int Datacolumn arbeiten gibt es Fehler von dieser Methode geworfen wie:Ausdruck des Typs 'System.Int32' kann nicht für Parameter des Typs 'System.Object' der Methode 'Boolean Equals (System.Object)'

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

meine Methode Code:

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

hier ist meine Frage, dass ich gefeuert:

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

Hier schließe ich mein query.GetType(). ToString() Ergebnis für ein besseres Verständnis Arten von Spalten, die ich darauf operieren.

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

Welche Zeile ist die Ausnahme? – thumbmunkeys

+0

aus der Body-Zeile von group_id Fall. zeige aktualisierte Frage –

Antwort

9

EDIT

die Lösung in this question gefunden. Sie müssen den Ausdruck Object vor dem Aufruf die Equals(object) Methode konvertieren:

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

Nicodemus13 ‚s Vorschlag ausdrücklich Einstellung searchExpression‘ s Typs Object in erster Linie sollte auch funktionieren.

Original-

Ich habe nicht das Problem noch nicht gefunden, aber ich habe das Problem in einer SSCCE mit LINQPad reproduziert:

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

Diese Zeile:

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

kehrt a MethodInfo für das Verfahren Int32?.Equals (Object other). Beachten Sie, dass der Parametertyp wie erwartet object, nicht Int32 (oder Int32?) ist.

Der Grund ist typeof(Int32?) ist System.Nullable<Int32>, die nur die Equals(object) Methode hat.

+0

das funktioniert. Aber wie auch immer, bei Fällen von FileSize, TotalFileSize habe ich nie ein Problem wie dieses gefunden. –

+0

Ich denke, das liegt daran, dass diese in Ihrer Abfrage nicht wirklich erscheinen, so dass die entsprechende 'case'-Anweisung niemals ausgeführt wird. – Rik

+0

Können wir Probleme wie die Konvertierung zum Objekt haben, falls wir mit Int64 arbeiten? –

2

Herumspielen mit diesem in LinqPad, ich denke, das Problem um ist:

searchExpression = Expression.Constant(_int1);

, wenn Sie anrufen:

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

Die Equals Methode, die Sie zu nennen sind versucht, ist object.Equals(object) und der Compiler teilt Ihnen mit, dass der Typ int? nicht der Typ object ist, den die Methode erwartet.

Die einfachste Fix (obwohl ich nicht sicher bin, dass der Gesamt Code funktioniert, wenn dieser spezielle Fehler weggeht) ist die Überlastung der Expression.Constant die Sie auf einen Anruf zu ändern, die den Typen gibt an, dass Equals erwartet:

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

Dies wird jedoch compile- ein paar Dinge gibt es zu beachten.

  1. Ihre ursprüngliche Expression.Constant(_int1) Ergebnisse in einem ConstantExpression mit Typeint nicht int?. Sie müssen den Nullable-Typ angeben, wenn Sie das benötigen (Expression.Constant(_int1, typeof(int?))). Allerdings musst du es wie oben beschrieben auf object umwandeln.

  2. containsMethod = typeof(Int32?).GetMethod("Equals", new[] { typeof(Int32?) }); angeben sollte sowieso nicht funktionieren, da gibt es keine solche Methode int?.Equals(int?), die Equals Verfahren die Überschreibung der Methode auf der System.Object Klasse ist, die einen object Parameter annimmt und ist die Wurzel des Problems. Sie können auch verwenden: typeof(object).GetMethod("Equals", new[] { typeof(object) }); als das ist die richtige Erklärung.

Wie ich schon sagte, es mit object kompilieren sollte, ob der Code tut, was Sie erwarten, ich bin nicht sicher, aber ich denke schon. Ich freue mich darauf zu sehen, ob es funktioniert :)

+0

danke u..es funktioniert. aber wie auch immer, ich frage mich, ich brauche diese Technik nicht für Int64 ?. –

+0

Sie sagen, dass (Ihr) genau der gleiche Code ist, aber das Ersetzen von 'Int32?' Durch 'Int64?' Löst nicht die ursprüngliche Ausnahme aus? – nicodemus13

+0

nicht ersetzen bedeutet, ich habe bereits Int64? was läuft gut. Warum Int32? Fehler so bekommen. –

Verwandte Themen