有没有办法可以从包含代码的字符串动态定义谓词主体?
这可能是一个愚蠢的问题,但就这样吧。 我希望能够动态构造一个谓词 < T> 来自从数据库 VARCHAR 列解析的字符串或任何字符串。 例如,假设数据库中的列包含以下字符串:
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> (或任何其他匿名/扩展)方法?
This is probably a stupid question, but here goes. I would like to be able to dynamically construct a predicate < T > from a string parsed from a database VARCHAR column, or any string, for that matter. For example, say the column in the database contained the following string:
return e.SomeStringProperty.Contains("foo");
These code/string values would be stored in the database knowing what the possible properties of the generic "e" is, and knowing that they had to return a boolean. Then, in a magical, wonderful, fantasy world, the code could execute without knowing what the predicate was, like:
string predicateCode = GetCodeFromDatabase();
var allItems = new List<SomeObject>{....};
var filteredItems = allItems.FindAll(delegate(SomeObject e) { predicateCode });
or Lambda-ized:
var filteredItems = allItems.FindAll(e => [predicateCode]);
I know it can probably never be this simple, but is there a way, maybe using Reflection.Emit, to create the delegate code dynamically from text and give it to the FindAll < T > (or any other anonymous/extension) method?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
C# 和 VB 编译器可从 .NET Framework 中获取:
C# CodeDom Provider
但请注意,这样您最终会得到一个单独的程序集(只有在单独的 AppDomain 中才能卸载)。 仅当您可以立即编译所需的所有谓词时,此方法才可行。 否则会涉及太多的开销。
System.Reflection.Emit 是一个很棒的 API,用于为 CLR 动态发出代码。 不过使用起来有点麻烦,必须学习CIL。
LINQ 表达式树是一个易于使用的后端(编译为 CIL),但您必须编写自己的解析器。
我建议您查看一种在 CLR(或 DLR)上运行的“动态语言”,例如 IronPython。 如果您问我的话,这是实现此功能的最有效方法。
The C# and VB compilers are available from within the .NET Framework:
C# CodeDom Provider
Be aware though, that this way you end up with a separate assembly (which can only be unloaded if it's in a separate AppDomain). This approach is only feasible if you can compile all the predicates you are going to need at once. Otherwise there is too much overhead involved.
System.Reflection.Emit is a great API for dynamically emitting code for the CLR. It is, however, a bit cumbersome to use and you must learn CIL.
LINQ expression trees are an easy to use back-end (compilation to CIL) but you would have to write your own parser.
I suggest you have a look at one of the "dynamic languages" that run on the CLR (or DLR) such as IronPython. It's the most efficient way to implement this feature, if you ask me.
可以使用 emit,但您需要构建自己的解析器。
编辑
我记得在 ScottGu 的 PDC 主题演讲中,他展示了一个使用 CLI 版本的 .net 框架的功能,类似于 Ruby 的 eval,但我找不到可以证实这一点的 URL。 我将其设为社区维基,以便任何拥有良好链接的人都可以添加它。
It is possible using emit, but you'd be building your own parser.
EDIT
I remember that in ScottGu's PDC keynote, he showed a feature using the CLI version of the .net framework that resembled Ruby's eval, but I can't find a URL that can corroborate this. I'm making this a commnity wiki so that anyone who has a good link can add it.
查看 Dynamic Linq 项目,它可以实现所有这些功能以及更多功能!
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
太棒了对于简单的东西,比如用户选择的 orderby 或 where 子句
Check out the Dynamic Linq project it does all this and more!
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Great for simple stuff like user selected orderby's or where clauses
我放弃了动态 linq,因为它在我想要搜索集合的方式上受到限制,除非你证明我错了。
我的过滤器需要是:在订单列表中,过滤该列表,以便我只有该订单中的项目集合中包含名称为“可口可乐”的项目的订单。
因此,这将导致以下方法:
orders.Findall(o => o.Items.Exists(i => i.Name == "coca cola"))
在动态 linq 中,我没有找不到任何方法可以做到这一点,所以我从
CodeDomProvicer
开始。我使用包含动态构建的
FindAll
方法创建了一个新的Type
方法:当我尝试构建此程序集时:
我收到错误:
为什么不是编译器能够编译谓词吗?
I stepped off the dynamic linq because it's limited in ways I want to search a collection, unless you prove me wrong.
My filter needs to be: in a list of orders, filter the list so that I have only the orders with in the collection of items in that order, an item with the name "coca cola".
So that will result to a method of:
orders.Findall(o => o.Items.Exists(i => i.Name == "coca cola"))
In dynamic linq I didn't find any way to do that, so I started with
CodeDomProvicer
.I created a new
Type
with a method which contains my dynamically builtFindAll
Method:when I try to build this assembly:
I'm getting the error:
Why isn't the compiler able to compile the predicate?