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

Ari*_*edi 0 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);
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下Category是一个属性EventListItem.调用时抛出此异常ParseLambda():

Unknown identifier 'Regex'.

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

Sph*_*xxx 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);
Run Code Online (Sandbox Code Playgroud)

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

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

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

    typeof(System.Text.RegularExpressions.Regex), 
    typeof(System.Text.RegularExpressions.RegexOptions),
};
Run Code Online (Sandbox Code Playgroud)


编辑:复杂的参数值
如果我们需要在方法调用中包含更复杂的参数,例如组合的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);
Run Code Online (Sandbox Code Playgroud)

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