Search code examples
c#.netlambdadelegatesexpression-trees

Call Static Method in expression.call with arguments


I have extended the string class for Contains method. I'm trying to call it in Expression.Call, but how to pass the argument properly?

Code: String Contains method:

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

In Expression calling as :

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

Error:

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.

How to call the parameter in miContain for following Call() methods?

I have updated the Code.


Solution

  • You are not specifying all parameters. If you create expressions for all, it works:

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