gpt4 book ai didi

c# - 如何使用 ExpressionTree 创建一个使用 Regex 的谓词

转载 作者:太空宇宙 更新时间:2023-11-03 21:02:26 28 4
gpt4 key购买 nike

我正在手动构建一个谓词来过滤 CollectionView 中的数据,我想添加通过用户提供的 Regex 过滤特定字段的功能。直接编写谓词会给出如下内容:

string userRegex = "abc.+";
Predicate<object> myPredicate = p => Regex.IsMatch(((MyType).p).MyField, userRegex);

所以我可以将模式传递到我的谓词工厂并执行类似这样的操作(出于我的头脑并没有尝试 - 不确定 Call 语法):

string userRegex = "abc.+";
var paramObject = Expression.Parameter(typeof(object), "p");
var paramMyType = Expression.TypeAs(paramObject, typeof(MyType));
var propMyField = Expression.Property(paramMyType, "MyField");
var constRegex = Expression.Constant(userRegex);

var methodInfo = typeof(Regex).GetMethod("IsMatch", new Type[] { typeof(string), typeof(string) } );
var params = new Expression[] { propMyField, constRegex }

var lamdaBody = Expression.Call(methodInfo, params);
var lamda = Expression.Lambda<Func<object, bool>>(lamdaBody, paramObject);
var myPredicate = new Predicate<object>(lamda.Compile());

但我的直觉告诉我,这将创建一个表达式,该表达式将在每次调用谓词时根据模式重建正则表达式。这种直觉是否正确?

如果我的直觉是正确的,那么是否可以在创建使用它的表达式之前预先构建正则表达式?如果是这样,怎么做到的?

或者,如果我完全偏离正轨,这应该由谁来完成?

(我的 Call 语法是否正确??)


编辑

只是为了澄清一些事情。

  1. 我正在构建的谓词是针对 CollectionView.Filter 的, 所以签名必须是 Predicate<object>
  2. 尽管我在示例中只显示了一个正则表达式,但我实际(动态)构建的谓词还有许多其他子句。为清楚起见,其余部分已被省略。
  3. 谓词本身仅在用户单击某些选项然后按下按钮后才构建。即使与其他 UI 事件相比,这种情况也很少发生。
  4. 应用谓词时,它将应用于支持 CollectionView 的集合中的 10,000 到 20,000(或更多)对象
  5. 我的程序中几乎没有其他正则表达式,所以我认为 Filip 关于缓存最后 15 个模式的观察意味着我的直觉可能是错误的。
  6. 但我仍然想做一些像 Filip 的回答那样的事情,并以某种方式在我正在构建的表达式树中捕获正则表达式的编译版本。

最佳答案

首先,根本不清楚为什么要使用表达式树/动态代码生成。性能真的那么重要,以至于您负担不起创建复合 Predicate 并加入其他(较小的)Predicate 吗?

其次,我不确定我是否理解您在更改代码以使用已编译的 RegEx 时看到的问题。以下代码是否符合您的要求:

    static Predicate<object> CreateRegExPredicateSmart(string pattern)
{
var regex = new Regex(pattern, RegexOptions.Compiled);
var paramObject = Expression.Parameter(typeof(object), "p");
var paramMyType = Expression.TypeAs(paramObject, typeof(MyType));
var propMyField = Expression.Property(paramMyType, "MyField");
var constRegex = Expression.Constant(regex);

var methodInfo = typeof(Regex).GetMethod("IsMatch", new Type[] { typeof(string) });
var paramsEx = new Expression[] { propMyField };

var lamdaBody = Expression.Call(constRegex, methodInfo, paramsEx);
Expression<Func<object, bool>> lamdaSmart = Expression.Lambda<Func<object, bool>>(lamdaBody, paramObject);

return new Predicate<object>(lamdaSmart.Compile());
}

注意 RegexOptions.Compiled actually does可能不完全符合您的预期,但在您的上下文中似乎有意义。

关于c# - 如何使用 ExpressionTree 创建一个使用 Regex 的谓词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44089953/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com