2015-08-10 24 views
6

Rozszerzyłem klasę ciągów dla metody Contains. Próbuję nazwać to w Expression.Call, ale jak poprawnie przekazać argument?Wywołanie metody statycznej w wyrażeniu.call z argumentami

Kod: String Zawiera metoda:

public static class StringExts 
{ 
    public static bool NewContains(this string source, string ValToCheck, StringComparison StrComp) 
    { 
     return source.IndexOf(ValToCheck, StrComp) >= 0; 
    } 
} 

ekspresji wywołanie jak:

public class Person { public string Name {get; set;} } 

public class Persons { 
    public List<Person> lstPersons {get; set;} 
    public Persons() { 
     lstPersons = new List<Person>();  
    } 
} 

public class Filter 
{ 
    public string Id { get; set; } 
    public Operator Operator { get; set; } 
    public string value { get; set; } 
} 

public void Main() 
{ 
    //Get the json. 
    //"Filters": [{"id": "Name", "operator": "contains", "value": "Microsoft"}] 

    Filter Rules = JsonConvert.DeserializeObject<Filter>(json); 

    // Get the list of person firstname. 
    List<Person> lstPerson = GetFirstName(); 

    ParameterExpression param = Expression.Parameter(typeof(Person), "p"); 
    Expression exp = null; 

    exp = GetExpression(param, rules[0]); 

    //get all the name contains "john" or "John" 
    var filteredCollection = lstPerson.Where(exp).ToList(); 

} 

private Expression GetExpression(ParameterExpression param, Filter filter){ 
    MemberExpression member = Expression.Property(param, filter.Id); 
    ConstantExpression constant = Expression.Constant(filter.value); 

    Expression bEXP = null; 

    switch (filter.Operator) 
    { 
     case Operator.contains: 
      MethodInfo miContain = typeof(StringExts).GetMethod("NewContains", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); 
      return Expression.Call(miContain, member, constant , Expression.Constant(StringComparison.OrdinalIgnoreCase));; 
      break; 
    } 
} 

Błąd:

An unhandled exception of type 'System.ArgumentException' occurred in System.Core.dll.Additional information: Static method requires null instance, non-static method requires non-null instance.

Jak wywołać parametr w miContain dla następujących Call() metod?

Zaktualizowałem kod.

+1

Nieco off-topic, ale jesteś świadomy już istnieje [ 'String.Contains'] (https://msdn.microsoft.com/en-us/ biblioteka/dy85x1sa (v = vs.110) .aspx) metoda? – Sayse

+0

@ Sayse Nie ma takiego, który bierze StringComparison jako dodatkowy argument. –

Odpowiedz

6

Nie określasz wszystkich parametrów. Jeśli tworzysz wyrażenia dla wszystkich, to działa:

ParameterExpression source = Expression.Parameter(typeof(string)); 
string ValToCheck = "A"; 
StringComparison StrComp = StringComparison.CurrentCultureIgnoreCase; 

MethodInfo miContain = typeof(StringExts).GetMethod("NewContains", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); 
var bEXP = Expression.Call(miContain, source, Expression.Constant(ValToCheck), Expression.Constant(StrComp)); 

var lambda = Expression.Lambda<Func<string, bool>>(bEXP, source); 

bool b = lambda.Compile().Invoke("a"); 
+1

Dzięki za odpowiedź. Używam Expression w Linq.Where(), może być źródłem tak, że. Expression.call (miContain, członek, Expression.Constant (ValToCheck), Expression.Constant (StrComp) –

+2

Oczywiście, przekazać w "ParameterExpression". Zaktualizowałem moją odpowiedź –

+0

Twoje odpowiedzi również pomogły mi rozwiązać mój problem. Również @PatrickHofman cię może użyć ".Where (expressionCompiled)" w bardziej ogólny sposób, przeczytaj ten post na blogu www.pashov.net/code/dynamic+filters –

0

Nie podano wystarczającej liczby argumentów (2 do 3). NewContains ma trzy argumenty.

Ponadto, ponieważ ta metoda nie jest metodą instancji, nie można ustawić tego parametru. This overload looks better.

Prawdopodobnie powinieneś był sprawdzić overload list. W ten sposób znalazłem właściwą odpowiedź na to pytanie, nie znając go wcześniej.