在动态linq查询中调用Regex.IsMatch()

时间:2013-05-21 21:24:28

标签: c# regex dynamic-linq

我正在尝试调用Regex.IsMatch()并在动态linq查询中评估返回的结果。这就是我试过的:

public static LambdaExpression Parse(SearchQuery query)
{
    string compilableExpression = "Regex.IsMatch(Category.ToLower(), \"\\bSomeCat\\b\", RegexOptions.Compiled) == true";

    ParameterExpression parameter1 = System.Linq.Expressions.Expression.Parameter(typeof(EventListItem));
    ParameterExpression parameter2 = System.Linq.Expressions.Expression.Parameter(typeof(Regex));

    return System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { parameter1, parameter2 }, null, compilableExpression);
}

在这种情况下,CategoryEventListItem中的属性。调用ParseLambda()

时会抛出此异常

Unknown identifier 'Regex'

有没有办法调用方法?我遇到了Expression.Call()方法,但我不确定这是否是我正在寻找的。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:7)

我没有经常使用System.Linq.Dynamic,但这是让你的例子有效的方法:

1 - 您实际上只有一个输入对象EventListItem,所以删除参数2(正则表达式):

string compilableExpression = "Regex.IsMatch(Category.ToLower(), \"\\bSomeCat\\b\", RegexOptions.Compiled) == true";
ParameterExpression parameter1 = System.Linq.Expressions.Expression.Parameter(typeof(EventListItem));
return System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { parameter1 }, null, compilableExpression);

2 - DynamicExpression.ParseLambda()用于从输入对象中读取属性和方法。在其他类上使用方法(此处:Regex.IsMatch()仅限于一小组预定义类,默认情况下Regex不是其中之一。

因此,我们需要让解析器意识到“Regex”是一个类,而不是EventListItem上的属性。假设您已在项目中包含DynamicLinq.cs file,可以通过将Regex(和RegexOptions)添加到内部ExpressionParser.predefinedTypes数组来完成此操作:

static readonly Type[] predefinedTypes = {
    typeof(Object),
    typeof(Boolean),
    ...

    typeof(System.Text.RegularExpressions.Regex), 
    typeof(System.Text.RegularExpressions.RegexOptions),
};


编辑:复杂参数值
如果我们需要在方法调用中包含更复杂的参数,例如一个组合的RegexOptions枚举; RegexOptions.Compiled | RegexOptions.IgnoreCase,ParseLambda也接受values列表。

我们事先准备合并的枚举,并在该值列表中提交。在compilableExpression中,我们为我们提交的值包含占位符,以我们提交的相同顺序编制索引(此处我们只有一个值 - 索引0)

var options = RegexOptions.Compiled | RegexOptions.IgnoreCase;
string compilableExpression = "Regex.IsMatch(Category.ToLower(), \"\\bSomeCat\\b\", @0) == true";
ParameterExpression parameter1 = SLE.Expression.Parameter(typeof(EventListItem));
return SLD.DynamicExpression.ParseLambda(new[] { parameter1 },
                                         null,
                                         compilableExpression,
                                         options);

Bonus:因为compilableExpression中不再直接引用RegexOptions类/枚举,所以我们也不再需要在ExpressionParser.predefinedTypes中包含RegexOptions。