3

这可能是一个愚蠢的问题,但在这里。就此而言,我希望能够从从数据库 VARCHAR 列或任何字符串解析的字符串动态构造谓词 < T >。例如,假设数据库中的列包含以下字符串:

return e.SomeStringProperty.Contains("foo");

这些代码/字符串值将存储在数据库中,知道通用“e”的可能属性是什么,并且知道它们必须返回一个布尔值。然后,在一个神奇、奇妙、奇幻的世界中,代码可以在不知道谓词是什么的情况下执行,例如:

string predicateCode = GetCodeFromDatabase();
var allItems = new List<SomeObject>{....};
var filteredItems = allItems.FindAll(delegate(SomeObject e) { predicateCode });

或 Lambda 化:

var filteredItems = allItems.FindAll(e => [predicateCode]);

我知道它可能永远不会这么简单,但是有没有办法,也许使用 Reflection.Emit,从文本动态创建委托代码并将其提供给 FindAll < T > (或任何其他匿名/扩展)方法?

4

4 回答 4

1

查看 Dynamic Linq 项目,它完成了所有这些以及更多工作!

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

非常适合简单的东西,比如用户选择的 orderby 或 where 子句

于 2009-02-19T20:35:27.700 回答
1

C# 和 VB 编译器可从 .NET Framework 中获得:

C# CodeDom 提供程序

但请注意,这样您最终会得到一个单独的程序集(只有在单独的 AppDomain 中才能卸载它)。这种方法只有在您可以一次编译所有需要的谓词时才可行。否则会涉及太多开销。

System.Reflection.Emit 是一个很棒的 AP​​I,用于为 CLR 动态发出代码。但是,它使用起来有点麻烦,您必须学习 CIL。

LINQ 表达式树是一个易于使用的后端(编译为 CIL),但您必须编写自己的解析器。

我建议您看一下在 CLR(或 DLR)上运行的“动态语言”之一,例如IronPython。如果您问我,这是实现此功能的最有效方式。

于 2009-02-19T20:59:07.247 回答
0

可以使用emit,但您将构建自己的解析器。

编辑

我记得在 ScottGu 的 PDC 主题演讲中,他展示了一个使用 .net 框架的 CLI 版本的功能,该功能类似于 Ruby 的 eval,但我找不到可以证实这一点的 URL。我将其设为社区 wiki,以便任何拥有良好链接的人都可以添加它。

于 2009-02-19T20:50:57.090 回答
0

我退出了动态 linq,因为它在我想要搜索集合的方式上受到限制,除非你证明我错了。

我的过滤器需要是:在订单列表中,过滤列表,以便我只有在该订单的项目集合中的订单,一个名为“可口可乐”的项目。

所以这将导致一种方法:orders.Findall(o => o.Items.Exists(i => i.Name == "coca cola"))

在动态 linq 中,我没有找到任何方法来做到这一点,所以我从CodeDomProvicer. Type我使用包含我动态构建的方法的方法创建了一个新FindAll方法:

public static IList Filter(list, searchString)
{
   // this will by dynamically built code
   return orders.Findall(o => o.Items.Exists(i => i.Name == "coca cola"));
}

当我尝试构建这个程序集时:

CompilerResults results = provider.CompileAssemblyFromSource(parameters, sb.ToString());

我收到错误:

Invalid expression term ">"

为什么编译器不能编译谓词?

于 2009-07-03T09:21:11.447 回答