To jest uproszczona wersja pierwotnego problemu.
Mam klasę o nazwie Osoba:
public class Person {
public string Name { get; set; }
public int Age { get; set; }
public int Weight { get; set; }
public DateTime FavouriteDay { get; set; }
}
... i powiedzmy przykład:
var bob = new Person {
Name = "Bob",
Age = 30,
Weight = 213,
FavouriteDay = '1/1/2000'
}
Chciałbym napisać następujący tekst jako ciąg w moim ulubionym edytorze tekstu ....
(Person.Age > 3 AND Person.Weight > 50) OR Person.Age < 3
Chciałbym wziąć ten ciąg i moją instancję obiektu i ocenić TRUE lub FALSE - tj. Oszacować Func <Person, bool> na instancji obiektu.
Oto moje aktualne przemyślenia:
- Zaimplementuj podstawową gramatykę w ANTLR, aby obsługiwać podstawowe porównania i operatory logiczne. Myślę o skopiowaniu priorytetu Visual Basic i niektórych funkcji tutaj: http://msdn.microsoft.com/en-us/library/fw84t893(VS.80).aspx
- Poproś ANTLR o utworzenie odpowiedniego AST z dostarczonego ciągu.
- Przejdź przez AST i użyj Predicate Builder , aby dynamicznie utworzyć obiekt Func <Person, bool>
- Oceń predykat względem instancji Person zgodnie z wymaganiami
Moje pytanie brzmi: czy całkowicie przesadziłem? jakieś alternatywy?
EDYCJA: wybrane rozwiązanie
Zdecydowałem się użyć Dynamic Linq Library, a konkretnie klasy Dynamic Query dostarczonej w LINQSamples.
Kod poniżej:
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();
}
}
}
Wynik jest typu System.Boolean iw tym przypadku ma wartość TRUE.
Wielkie dzięki dla Marc Gravell.
Dołącz pakiet nuget System.Linq.Dynamic , dokumentacja tutaj