【发布时间】:2020-03-04 21:50:35
【问题描述】:
我想将表达式存储在数据库中以维护规则引擎。表达式就是这个例子的形式:
Expression<Func<MyTerm, bool>> expression = t => t.MyProperty == SomeValue;
我面临的问题是我必须在运行时创建 MyTerm。为了仍然能够使用 MyTerm 作为 lambda 表达式的参数,我使用 ExpandoObject 实现了一个解决方案,如下所示:
public class MyTerm
{
ExpandoObject ParameterSet;
public void AddParameter(string name, object value)
{
IDictionary<string, object> dictionary = ParameterSet as IDictionary<string, object>;
if (dictionary.ContainsKey(name))
{
dictionary[name] = value;
}
else
{
dictionary.Add(name, value);
}
}
public string GetString(string name)
{
IDictionary<string, object> dictionary = ParameterSet as IDictionary<string, object>;
if (dictionary.ContainsKey(name))
{
return (string)dictionary[name];
}
throw new KeyNotFoundException("Term does not contain parameter {name}.");
}
问题是,我获得了能够在运行时向 MyTerm 添加参数的优势,但是我必须为每个 getter 指定返回类型,而不是能够使用上面的语法:
t.MyProperty
有没有办法使用动态对象作为 lambda 表达式的输入,或者有没有办法为这样的类编写扩展方法以返回对象而不是特定类型?我可以像这样编译表达式:
public static Func<MyTerm, bool> Compile(string body)
{
ParameterExpression term = Expression.Parameter(typeof(MyTerm), typeof(MyTerm).Name);
LambdaExpression exp = DynamicExpressionParser.ParseLambda(new[] { term }, typeof(bool), body);
return (Func<DynamicTerm, bool>)exp.Compile();
}
static void Main(string[] args)
{
MyTerm term = new MyTerm();
term.AddParameter("SomeParameter", "SomeValue");
Func<MyTerm, bool> IsGreaterThanSomeParameter = Compile("MyTerm.GetString(\"SomeParameter\")== SomeValue);
bool result = IsGreaterThanSomeParameter(term);
Console.WriteLine(result);
Console.ReadLine();
}
我想存储独立于特定实现的 lambda 表达式,因此如果另一个服务尝试将这些表达式编译回函数,则该语法应该是开箱即用的。没有任何工作方法的吸气剂。 提前谢谢你。
【问题讨论】:
-
我仍然不明白:1) 你如何在数据库中存储表达式,2) ParameterSet 与 MyTerm 的关系,3) 你为什么要尝试使用动态。如果你的表达式是固定的,它只会访问 MyTerm 上一组已知的属性,所以你不需要动态添加属性,确定吗?
-
1) 这与我面临的问题并没有真正的关系。我只是想为应用程序提供上下文。 2) ParameterSet 是一个 ExpandoObject,它使我能够在运行时向 MyTerm 类添加参数。 3)我的表情是固定的。但不是我的一组可能的表达方式。可以将参数添加到 MyTerm 中,也可以添加与这些参数相关的表达式
-
但是您不会在运行时将属性添加到
MyTerm。您添加了一个GetString方法,该方法恰好使用ExpandoObject作为字典,但您从不调用GetString。你不会在任何地方使用dynamic。 -
我添加了我的 AddParameter 方法。这是我在运行时添加参数的方法
-
您仍然没有调用
GetString的任何内容,并且您仍然没有将ExpandoObject用作Dictionary<string, object>以外的任何其他内容
标签: c# asp.net dynamic lambda expandoobject