有没有办法可以从包含代码的字符串中动态定义Predicate主体?
这可能是一个愚蠢的问题,但这里有。 我希望能够从数据库VARCHAR列或任何字符串解析的字符串动态构造谓词。 例如,假设数据库中的列包含以下字符串:
return e.SomeStringProperty.Contains("foo");
这些代码/字符串值将存储在数据库中,知道通用“e”的可能属性是什么,并且知道它们必须返回布尔值。 然后,在一个神奇,美妙,幻想的世界中,代码可以在不知道谓词是什么的情况下执行,例如:
string predicateCode = GetCodeFromDatabase(); var allItems = new List{....}; var filteredItems = allItems.FindAll(delegate(SomeObject e) { predicateCode });
或Lambda化:
var filteredItems = allItems.FindAll(e => [predicateCode]);
我知道它可能永远不会这么简单,但有没有办法,也许使用Reflection.Emit,从文本动态创建委托代码并将其提供给FindAll (或任何其他匿名/扩展)方法?
C#和VB编译器可从.NET Framework中获得:
C#CodeDom提供程序
但请注意,这样您最终会得到一个单独的程序集(如果它位于单独的AppDomain中,则只能卸载它)。 只有在您可以一次编译所有需要的谓词时,此方法才可行。 否则涉及太多的开销。
System.Reflection.Emit是一个很棒的API,用于动态发送CLR代码。 但是,它使用起来有点麻烦,你必须学习CIL。
LINQ表达式树是一个易于使用的后端(编译到CIL),但您必须编写自己的解析器。
我建议您查看一下在CLR(或DLR)上运行的“动态语言”,例如IronPython 。 如果你问我,这是实现这个function最有效的方法。
查看Dynamic Linq项目它完成所有这些以及更多!
非常适合用户选择的orderby或where子句等简单的东西
可以使用emit ,但是你要构建自己的解析器。
编辑
我记得在ScottGu的PDC主题演讲中,他展示了一个使用.net框架的CLI版本的function,类似于Ruby的eval,但我找不到可以证实这一点的URL。 我正在将它变成一个社区维基,这样任何拥有良好链接的人都可以添加它。
我放弃了动态linq,因为它在我想要搜索集合的方式上受到限制,除非你certificate我错了。
我的filter需要是:在订单列表中,过滤列表,以便我只有订单中的订单,该订单包含名称为“coca cola”的项目。
这将产生一个方法: 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 ">"
为什么编译器不能编译谓词?