Ini adalah versi sederhana dari masalah aslinya.
Saya memiliki kelas yang disebut Person:
public class Person {
public string Name { get; set; }
public int Age { get; set; }
public int Weight { get; set; }
public DateTime FavouriteDay { get; set; }
}
... dan katakanlah sebuah instance:
var bob = new Person {
Name = "Bob",
Age = 30,
Weight = 213,
FavouriteDay = '1/1/2000'
}
Saya ingin menulis yang berikut sebagai string di editor teks favorit saya ....
(Person.Age > 3 AND Person.Weight > 50) OR Person.Age < 3
Saya ingin mengambil string ini dan contoh objek saya dan mengevaluasi BENAR atau SALAH - yaitu mengevaluasi Func <Person, bool> pada instance objek.
Inilah pemikiran saya saat ini:
- Menerapkan tata bahasa dasar di ANTLR untuk mendukung Operator Perbandingan dan Logika dasar. Saya berpikir untuk menyalin prioritas Visual Basic dan beberapa fitur di sini: http://msdn.microsoft.com/en-us/library/fw84t893(VS.80).aspx
- Minta ANTLR membuat AST yang cocok dari string yang disediakan.
- Berjalan AST dan gunakan kerangka kerja Predicate Builder untuk secara dinamis membuat Func <Person, bool>
- Mengevaluasi predikat terhadap instance Person sesuai kebutuhan
Pertanyaan saya adalah apakah saya benar-benar overbaked ini? ada alternatif?
EDIT: Solusi Terpilih
Saya memutuskan untuk menggunakan Dynamic Linq Library, khususnya kelas Dynamic Query yang disediakan di LINQSamples.
Kode di bawah ini:
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();
}
}
}
Hasilnya adalah tipe System.Boolean, dan dalam hal ini BENAR.
Banyak terima kasih kepada Marc Gravell.
Termasuk System.Linq. Paket nuget dinamis, dokumentasi di sini