在 expression.call 中使用参数调用静态方法

Posted

技术标签:

【中文标题】在 expression.call 中使用参数调用静态方法【英文标题】:Call Static Method in expression.call with arguments 【发布时间】:2015-11-02 06:45:08 【问题描述】:

我已经为Contains 方法扩展了字符串类。我正在尝试在Expression.Call 中调用它,但是如何正确传递参数?

代码:字符串包含方法:

public static class StringExts

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

在表达式中调用为:

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;
    
 

错误:

System.Core.dll 中发生“System.ArgumentException”类型的未处理异常。附加信息:静态方法需要空实例,非静态方法需要非空实例。

如何调用miContain中的参数以跟随Call()方法?

我已经更新了代码。

【问题讨论】:

有点跑题但你知道已经有一个String.Contains 方法吗? @Sayse 没有一个将 StringComparison 作为附加参数。 【参考方案1】:

您没有指定所有参数。如果您为所有人创建表达式,它会起作用:

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

【讨论】:

感谢您的回答。我在 Linq.Where() 中使用表达式,可以是这样的成员。 Expression.call(miContain, 成员, Expression.Constant(ValToCheck), Expression.Constant(StrComp) 当然,传入ParameterExpression。更新了我的答案。 您的回答也帮助我解决了我的问题。另外@PatrickHofman,您可以以更通用的方式使用“.Where(expressionCompiled)”,阅读这篇博文 www.pashov.net/code/dynamic+filters【参考方案2】:

您没有指定足够的参数(2 对 3)。 NewContains 有三个参数。

另外,由于此方法不是实例方法,因此您不能设置 this 参数。 This overload looks better.

您可能应该检查过overload list。这就是我在事先不知道的情况下找到这个问题的正确答案的方法。

【讨论】:

以上是关于在 expression.call 中使用参数调用静态方法的主要内容,如果未能解决你的问题,请参考以下文章

Expression.Call 在简单的 lambda 表达式中。可能吗?

在 C++ 中使用默认参数调用函数

Oracle:不允许使用在插入语句中调用函数的符号参数?

在函数调用中“使用严格”和命名参数

在 C 中,给定参数的变量列表,如何使用它们构建函数调用?

在 onswipe jquery 中使用参数调用外部函数