【发布时间】:2010-10-23 17:02:49
【问题描述】:
这是原始问题的简化版本。
我有一个名为 Person 的类:
public class Person {
public string Name { get; set; }
public int Age { get; set; }
public int Weight { get; set; }
public DateTime FavouriteDay { get; set; }
}
...让我们说一个实例:
var bob = new Person {
Name = "Bob",
Age = 30,
Weight = 213,
FavouriteDay = '1/1/2000'
}
我想在我最喜欢的文本编辑器中将以下内容写为 字符串....
(Person.Age > 3 AND Person.Weight > 50) OR Person.Age < 3
我想获取这个字符串和我的对象实例并评估 TRUE 或 FALSE - 即评估对象实例上的 Func
这是我目前的想法:
- 在 ANTLR 中实现基本语法以支持基本的比较和逻辑运算符。我正在考虑在此处复制 Visual Basic 优先级和一些功能集:http://msdn.microsoft.com/en-us/library/fw84t893(VS.80).aspx
- 让 ANTLR 根据提供的字符串创建合适的 AST。
- 遍历 AST 并使用 Predicate Builder 框架动态创建 Func
- 根据需要根据 Person 实例评估谓词
我的问题是我完全把它烤过头了吗?有其他选择吗?
编辑:选择的解决方案
我决定使用动态 Linq 库,特别是 LINQSamples 中提供的动态查询类。
代码如下:
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();
}
}
}
结果是 System.Boolean 类型,在本例中为 TRUE。
非常感谢 Marc Gravell。
包括System.Linq.Dynamicnuget 包,文档here
【问题讨论】:
-
感谢您发布完整的解决方案代码以及您的问题。非常感谢。
-
如果你有一个收藏或人并且想要过滤一些元素怎么办? Person.Age > 3 AND Person.Weight > 50 ?
-
谢谢。我找不到 DynamicExpression.ParseLambda()。它在哪个命名空间和程序集中?
-
一切都好.. 命名空间之间存在歧义。需要 - 使用 E = System.Linq.Expressions;使用 System.Linq.Dynamic;
-
为什么它使用'AND'而不是'&&'。不应该是C#代码吗?
标签: c# lambda antlr dsl predicate