2009-02-19 61 views
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 }); 

或λ-美化版:那麼,在一個神奇,美妙,奇幻世界中,代碼可能不知道什麼是謂語是,就像執行

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

我知道這可能永遠是這很簡單,但是有沒有辦法,可能使用Reflection.Emit,從文本中動態創建委託代碼,並將其提供給FindAll < T>(或任何其他匿名/擴展)方法?

回答

1

查看Dynamic Linq項目,它可以完成所有這些工作!

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

大像用戶選擇排序依據的或者where子句

+0

不錯,你使這個社區維基,但我找不到任何有關「動態鏈接項目」提供一些背景給你的答案。你可以請添加一個URL? – 2009-02-19 20:51:58

+0

動態Linq的問題(據我所知)是我無法在Predicate中使用任何複雜的非SQL代碼。 「allItems」列表不是源自數據庫的對象,它實際上是一個字符串列表,我希望能夠以各種不在源代碼中定義的方式進行測試。 – 2009-02-19 20:52:01

0

它使用emit可以簡單的東西,但你可以建立自己的解析器。

編輯

我記得在ScottGu的PDC主題演講中,他表現出的特徵使用.NET框架,類似於Ruby的EVAL的CLI版本,但我無法找到能夠證實這個URL。我將此作爲一個社區wiki,以便任何有良好關聯的人都可以添加它。

1

的C#和VB編譯器可從.NET Framework中:

C# CodeDom Provider

要知道,雖然,那這樣,你最終有一個單獨的組件(如果它在這隻能卸載一個單獨的AppDomain)。這種方法只有在您可以一次編譯所有需要的謂詞時纔可行。否則,涉及的開銷太多。

System.Reflection.Emit是一個很好的API,用於動態發佈CLR的代碼。但是,使用起來有點麻煩,你必須學習CIL。

LINQ表達式樹是一個易於使用的後端(編譯爲CIL),但您必須編寫自己的解析器。

我建議你看一下在CLR(或DLR)上運行的「動態語言」之一,如IronPython。如果你問我,這是實現此功能的最有效方式。

0

我走了動態LINQ,因爲它的方式有限,我想搜索一個集合,除非你證明我錯了。

我的過濾器需要:在訂單列表中,過濾列表,以便我只有訂單中的物品集合中的訂單,名稱爲「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 ">" 

爲什麼編譯器不能編譯謂詞?

相關問題