在动态linq查询中调用Regex.IsMatch() [英] Invoking Regex.IsMatch() inside a dynamic linq query

查看:92
本文介绍了在动态linq查询中调用Regex.IsMatch()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 公共静态LambdaExpression解析(SearchQuery查询){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));返回System.Linq.Dynamic.DynamicExpression.ParseLambda(new [] {parameter1,parameter2},null,compilableExpression);} 

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

未知标识符"Regex" .

是否可以调用该方法?我遇到过 Expression.Call()方法,但是我不确定这是否是我想要的.感谢您的帮助.

解决方案

我没有使用过 System.Linq.Dynamic ,但这是使示例工作的一种方法:

1-您实际上只有一个输入对象,即 EventListItem ,因此删除parameter2(Regex):

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

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

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

 静态只读Type []预定义类型= {typeof(Object),typeof(布尔),...typeof(System.Text.RegularExpressions.Regex),typeof(System.Text.RegularExpressions.RegexOptions),}; 


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

我们事先准备了合并的枚举,并将其提交到该值列表中.在 compilableExpression 中,我们为提交的值添加了占位符,并以与提交它们的顺序相同的方式对其进行了索引(此处只有一个值-索引0)

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

奖金:由于RegexOptions类/枚举不再在compilableExpression中直接引用,因此我们也不再需要在ExpressionParser.predefinedTypes中包含RegexOptions.

I'm trying to invoke the Regex.IsMatch() and evaluate the returned result inside a dynamic linq query. This is what I tried:

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

In this case Category is a property in the EventListItem. This exception is thrown upon calling ParseLambda():

Unknown identifier 'Regex'.

Is there a way to invoke the method? I came across Expression.Call() method, but I'm not sure if that's what I'm looking for. Any help is appreciated.

解决方案

I haven't used System.Linq.Dynamic a lot, but here is a way to make your example work:

1 - You really only have one input object, your EventListItem, so remove parameter2 (Regex):

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() is made to read properties and methods from the input object. Using methods on other classes (here: Regex.IsMatch() is limited to a small set of predefined classes, and by default Regex isn't one of them.

Therefore, we somehow need to make the parser realize that "Regex" is a class and not a property on EventListItem. Assuming you have included the DynamicLinq.cs file in your project, this can be done by adding Regex (and RegexOptions) to the internal ExpressionParser.predefinedTypes array:

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

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


EDIT: Complex parameter values
If we need to include more complex parameters in our method calls, e.g. a combined RegexOptions enum; RegexOptions.Compiled | RegexOptions.IgnoreCase, ParseLambda also accepts a list of values.

We prepare the combined enum beforehand, and submit it in that values list. In compilableExpression we include placeholders for the values we submit, indexed in the same order we submit them (here we only have one value - index 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: Because the RegexOptions class/enum is no longer directly referenced in compilableExpression, we also no longer need to include RegexOptions in ExpressionParser.predefinedTypes.

这篇关于在动态linq查询中调用Regex.IsMatch()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆