Ich erstelle manuell ein Prädikat für das Filtern von Daten in einer CollectionView und ich möchte die Möglichkeit hinzufügen, ein bestimmtes Feld über einen Benutzer bereitgestellten Regex zu filtern. Schreibt das Prädikat würde direkt geben so etwas wie:Wie verwende ich einen ExpressionTree, um ein Prädikat zu erstellen, das einen Regex verwendet?
string userRegex = "abc.+";
Predicate<object> myPredicate = p => Regex.IsMatch(((MyType).p).MyField, userRegex);
So konnte ich das Muster in meine Prädikat Fabrik passieren und tue so etwas wie dies (aus der Spitze von meinem Kopf und nicht versuchte - nicht sicher über die Call-Syntax) :
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());
Aber mein Bauchgefühl sagt, dass dies einen Ausdruck zu schaffen, die die Regex aus dem Muster bei jedem Aufruf zum Prädikat wieder aufbauen werden. Ist das Bauchgefühl richtig?
Wenn mein Bauchgefühl korrekt ist, ist es dann möglich, die Regex vor dem Erstellen des Ausdrucks, der es verbraucht, zu erstellen? Und wenn ja, wie?
Oder wenn ich total aus dem Strahl, wer sollte dies getan werden?
(Auch ist mein Aufruf Syntax korrekt ??)
bearbeiten
einfach ein paar Dinge zu klären.
- Das Prädikat I ist für ein
CollectionView.Filter
bestimmt sind Gebäude, so dass die UnterschriftPredicate<object>
- Auch sein muss, obwohl ich nur eine Regex in meinem Beispiel zeige, bin das Prädikat mir eigentlich (dynamisch) Gebäude hat viele andere Klauseln. Der Rest wurde aus Gründen der Klarheit weggelassen.
- Das Prädikat selbst wird erst erstellt, nachdem der Benutzer einige Optionen angeklickt und dann eine Taste gedrückt hat. Dies geschieht selten im Vergleich zu anderen UI-Aktivitäten.
- Wenn das Prädikat angewendet wird, wird es auf 20.000 (oder mehr) bis 10.000 angewandt werden, um die Sammlung Objekte in der Collectionplay
- Es gibt nur sehr wenige andere Regex auf meinem Programm, so denke ich, Filip Beobachtung über die letzte Cachen 15 Muster bedeuten, dass mein Bauchgefühl wahrscheinlich falsch ist.
- Aber ich möchte immer noch etwas wie Filips Antwort machen und irgendwie eine kompilierte Version des Regex in den Ausdrucksbaum einfangen, den ich gerade erstelle.
'Benutzer geliefert Regex' - kein kugelsicherer Weg überhaupt. Was werden Sie in die Ausnahmebehandlung einfügen? – sln
@sln Ja Ich habe verschiedene Dinge aus Gründen der Klarheit weggelassen. Wie auch immer, in meiner tatsächlichen Anwendung hat die UI-Ebene (eigentlich das View-Modell, das an das Steuerelement gebunden ist, das alle Benutzerauswahlen für die Filterparameter behandelt) die Zeichenfolge bereits als Regex validiert, bevor die Daten irgendwo in die Nähe meiner Prädikat-Factory gelangen. –
'validiert die Zeichenfolge als eine Regex' so weit ich weiß, die einzige Möglichkeit, eine Dot-Net Regex zu validieren, ist es zu kompilieren, es sei denn, Sie wissen, wie Sie es vorher analysieren. Net tut. – sln