【问题标题】:DynamicExpresso : expression as variableDynamicExpresso : 表达式作为变量
【发布时间】:2018-08-29 05:21:28
【问题描述】:

假设我们有一个名为 TOTAL 的变量,它应该替换为 CClass 的 AProperty + BProperty。 我有一组 IQueryrable 的 CClass 对象,我想从这个集合中选择 (TOTAL + AProperty)。

AProperty 和 BProperty 是双精度值。我不想扩展我的类,因为它是我的数据库中的一个实体类,实际上 TOTAL 表达式是一个运行时、用户定义的变量。所以我不想通过反射或其他一些解决方案注入它们。我想让最终用户能够声明一些类似 MACRO 的变量,以基于它们创建更复杂的表达式。

有什么方法可以根据上述情况为我的解释器定义 TOTAL 表达式?

【问题讨论】:

  • “替换”是什么意思?你能用代码举例吗?
  • 我需要在 IQueryable 集上运行动态表达式。它是一组 CClass 类型,该类型有两个属性,称为 AProperty 和 BProperty。我需要定义一些预定义的表达式;例如作为表达式的 TOTAL 变量:(AProperty + BProperty)。所以当我在我的选择表达式中输入“TOTAL + AProperty”作为输入表达式时,它应该被计算为“AProperty + BProperty + BProperty”。事实上,TOTAL变量本身就是一个表达式。它就像一个保留变量是一个表达式。
  • 为什么必须是表达式?听起来像一个显式的属性获取器就足够了。喜欢:{ return AProperty + BProperty; } 您可以使用部分关键字扩展您的CClass。您希望计算在服务器上而不是在内存中进行吗?
  • APropertyBProperty是什么类型?
  • AProperty 和 BProperty 是双精度值。我不想扩展我的类,因为它是我的数据库中的一个实体类,实际上 TOTAL 表达式是一个运行时、用户定义的变量。所以我不想通过反射或其他一些解决方案注入它们。我想让最终用户能够声明一些类似 MACRO 的变量,以基于它们创建更复杂的表达式。

标签: c# .net linq dynamic-expresso


【解决方案1】:

你写道:

我们有一个名为 TOTAL 的变量,应将其替换为...

唉,LINQ 旨在从序列中选择数据。 LINQ 不会改变输入序列。

幸运的是,您还写道:

我有一组 IQueryrable 的 CClass 对象,我想从这个集合中选择 (TOTAL + AProperty)。

好的,我们可以做到。

我不想换班...

当然您不想更改实体类:您的实体类代表数据库中的表以及这些表之间的关系。您的函数不是通常属于您的数据库表的东西。因此它不属于那里。

因此,我们将为您的实体编写一个单独的扩展函数,而不是更改您的实体类。对于您的班级的用户,它看起来好像该函数是班级的一部分。见Extension Methods demystified

我不会为您的IQueryable<CClass> 编写函数,我会为任何可查询的对象序列编写函数

输入:某种类型的可查询对象序列和双精度值Value
另外:a> 属性选择器,用于选择具有 双精度值。
输出Value 和 get-property 的值之和。

public static double AddToProperty<TSource> (this IEnumerable<TSource> source, 
     Expression<Func<TSource, double>> propertySelector,        
     double value);
     where Tsource : class
{
     return source.Select(soureElement => propertySelector(sourceElement) + value);
}

用法:

var addedTotals = myDbContext.Students
    .AddToPropery( student => student.AnnualIncome, 3.14);

【讨论】:

  • 感谢您的详细解答。当我们了解运算符时,您提到的方式很好(如本例中的 + )。考虑我们有一个 Textarea 控件,我们的最终用户根据 CClass 中存在的所有属性编写自己的公式。例如,他可以将 TOTAL 变量设置为 (AProperty - (2*BProperty) 和 ... 。所以我真正想要的是一个类似于编译器的结构来将这些字符串表达式映射到 Linq 查询中。
  • 如果您的操作员键入一个表达式作为输入,您必须在运行时检查该表达式。显然这不能在编译时完成。这个表达式可以用在IQueryable 中你可以分解表达式看它是否可以执行,或者你只是使用表达式。只要您的IQueryableProvider 尝试编译Expression,就会抛出异常;如果表达式不正确。
  • 谢谢,我知道我应该在运行时检查它,但正如您更了解我,我们可以定义一个变量,该变量将在运行时通过反射替换为表达式。那是我想要的。
猜你喜欢
  • 1970-01-01
  • 2015-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多