Đây là một phiên bản đơn giản hóa của vấn đề ban đầu.
Tôi có một lớp gọi là Person:
public class Person {
public string Name { get; set; }
public int Age { get; set; }
public int Weight { get; set; }
public DateTime FavouriteDay { get; set; }
}
... và cho phép nói một ví dụ:
var bob = new Person {
Name = "Bob",
Age = 30,
Weight = 213,
FavouriteDay = '1/1/2000'
}
Tôi muốn viết đoạn dưới đây như một chuỗi trong trình soạn thảo văn bản yêu thích của tôi ....
(Person.Age > 3 AND Person.Weight > 50) OR Person.Age < 3
Tôi muốn lấy chuỗi này và đối tượng của tôi và đánh giá TRUE hoặc FALSE - tức là đánh giá Func <Person, bool> trên đối tượng.
Dưới đây là những suy nghĩ hiện tại của tôi:
- Thực hiện một ngữ pháp cơ bản trong ANTLR để hỗ trợ các toán tử logic và so sánh cơ bản. Tôi đang nghĩ đến việc sao chép quyền ưu tiên Visual Basic và một số tính năng tại đây: http://msdn.microsoft.com/en-us/l Library / fw84t893 (VS.80) .aspx
- Yêu cầu ANTLR tạo AST phù hợp từ chuỗi được cung cấp.
- Đi bộ AST và sử dụng Trình tạo dự đoán khung Trình tạo dự để tự động tạo Func <Person, bool>
- Đánh giá vị ngữ theo trường hợp của Người theo yêu cầu
Câu hỏi của tôi là tôi đã hoàn toàn vượt qua điều này? có phương án nào không?
EDIT: Giải pháp chọn
Tôi đã quyết định sử dụng Thư viện Linq động, cụ thể là lớp Truy vấn động được cung cấp trong LINQSamples.
Mã dưới đây:
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();
}
}
}
Kết quả là kiểu System.Boolean và trong trường hợp này là TRUE.
Rất cám ơn Marc Gravell.
Bao gồm gói nuget System.Linq.Docate , tài liệu tại đây