【发布时间】:2017-05-20 19:20:23
【问题描述】:
我正在手动构建一个谓词来过滤 CollectionView 中的数据,并且我想添加通过用户提供的正则表达式过滤特定字段的功能。直接编写谓词会给出如下结果:
string userRegex = "abc.+";
Predicate<object> myPredicate = p => Regex.IsMatch(((MyType).p).MyField, userRegex);
所以我可以将模式传递给我的谓词工厂并做这样的事情(我的头脑中没有尝试过 - 不确定调用语法):
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());
但我的直觉表明,这将创建一个表达式,该表达式将从每次调用谓词时的模式中重建正则表达式。这种直觉正确吗?
如果我的直觉是正确的,那么是否可以在创建使用它的表达式之前预先构建正则表达式?如果有,怎么做?
或者,如果我完全不在意,应该由谁来做?
(我的调用语法也正确吗??)
编辑
只是为了澄清一些事情。
- 我正在构建的谓词注定是
CollectionView.Filter,所以签名必须是Predicate<object> - 尽管我在示例中只显示了一个正则表达式,但我实际构建的谓词(动态)还有许多其他子句。为清楚起见,其余部分已省略。
- 谓词本身仅在用户单击某些选项然后按下按钮后构建。即使与其他 UI 活动相比,这种情况也很少发生。
- 应用谓词时,它将应用于支持 CollectionView 的集合中的 10,000 到 20,000 个(或更多)对象
- 我的程序中很少有其他正则表达式,所以我认为 Filip 关于缓存最后 15 个模式的观察意味着我的直觉可能是错误的。
- 但我仍然想做类似 Filip 的回答,并以某种方式在我正在构建的表达式树中捕获正则表达式的编译版本。
【问题讨论】:
-
user supplied Regex- 根本不是防弹方式。你打算用异常处理做什么? -
@sln 是的,为了清楚起见,我省略了各种项目。无论如何,在我的实际应用程序中,UI 层(实际上是绑定到处理过滤器参数的所有用户选择的控件的视图模型)已经在数据到达我的谓词工厂附近之前将字符串验证为正则表达式。
-
validated the string as a Regex据我所知,验证 Dot-Net 正则表达式的唯一方法是编译它,除非您知道如何在 .Net 之前解析它。 -
我通常只是在帮助器中使用正则表达式创建一个帮助器方法。在这种情况下,助手可以返回一个布尔值。
-
@jdweng 我可以这样做,除了我已经解耦了所有东西并且过滤器视图模型、谓词工厂和集合视图模型都在不同的对象中。所以我需要将谓词处理一段要传递的数据。这样做会破坏这种脱钩。
标签: c# regex expression predicate