Dies ist eine vereinfachte Version des ursprünglichen Problems.
Ich habe eine Klasse namens Person:
public class Person {
public string Name { get; set; }
public int Age { get; set; }
public int Weight { get; set; }
public DateTime FavouriteDay { get; set; }
}
... und sagen wir eine Instanz:
var bob = new Person {
Name = "Bob",
Age = 30,
Weight = 213,
FavouriteDay = '1/1/2000'
}
Ich möchte Folgendes als Zeichenfolge in meinen bevorzugten Texteditor schreiben ...
(Person.Age > 3 AND Person.Weight > 50) OR Person.Age < 3
Ich möchte diesen String und meine Objektinstanz nehmen und TRUE oder FALSE auswerten, dh eine Func <Person, bool> auf der Objektinstanz auswerten.
Hier sind meine aktuellen Gedanken:
- Implementieren Sie eine grundlegende Grammatik in ANTLR, um grundlegende Vergleichs- und logische Operatoren zu unterstützen. Ich denke darüber nach, die Visual Basic-Priorität und einige der hier aufgeführten Funktionen zu kopieren: http://msdn.microsoft.com/en-us/library/fw84t893(VS.80).aspx
- Lassen Sie ANTLR aus einer bereitgestellten Zeichenfolge einen geeigneten AST erstellen.
- Gehen Sie durch den AST und verwenden Sie das Predicate Builder- Framework, um die Func <Person, bool> dynamisch zu erstellen
- Bewerten Sie das Prädikat nach Bedarf anhand einer Instanz von Person
Meine Frage ist, habe ich das total überbacken? irgendwelche Alternativen?
BEARBEITEN: Gewählte Lösung
Ich habe mich für die Dynamic Linq Library entschieden, insbesondere für die in den LINQSamples bereitgestellte Dynamic Query-Klasse.
Code unten:
using System;
using System.Linq.Expressions;
using System.Linq.Dynamic;
namespace ExpressionParser
{
class Program
{
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public int Weight { get; set; }
public DateTime FavouriteDay { get; set; }
}
static void Main()
{
const string exp = @"(Person.Age > 3 AND Person.Weight > 50) OR Person.Age < 3";
var p = Expression.Parameter(typeof(Person), "Person");
var e = System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { p }, null, exp);
var bob = new Person
{
Name = "Bob",
Age = 30,
Weight = 213,
FavouriteDay = new DateTime(2000,1,1)
};
var result = e.Compile().DynamicInvoke(bob);
Console.WriteLine(result);
Console.ReadKey();
}
}
}
Das Ergebnis ist vom Typ System.Boolean und in diesem Fall TRUE.
Vielen Dank an Marc Gravell.
Fügen Sie System.Linq.Dynamic nuget Paket, Dokumentation hier