2010-03-09 11 views
3

我有一個接口類似以下內容:獲取謂詞<T>酒店信息

public IEnumerable<IDocument> Search(Predicate<IDocument> predicate) { ... } 

其中一個的IDocument看起來是這樣的:

public interface IDocument 
{ 
    string Id {get; set;} 
    string Title {get; set;} 
    ... 
} 

我即將實現一個文件提供者,我必須分解Predicate的內容並提取屬性,以便爲我們目前沒有OR/M映射的文檔數據庫創建一個SQL字符串。例如:我想知道用戶是通過ID還是通過標題進行搜索,因此我知道我是否可以通過ID進行搜索,或者必須對Title執行LIKE搜索。

我一直很重地使用LINQ,但這是我第一次坐在管道的另一端...我已經讀了一些關於表達式樹和Reflection的文章,但是文章還沒有下降到位了。如何(如果?)我可以分解/反映謂詞,所以我得到一個參數列表,我可以拼湊成一個SQL字符串?我期待這樣的事情草圖:

public IEnumerable<IDocument> Search(Predicate<IDocument> predicate) 
{ 
    string id = DoSomeMagic(predicate, "Id"); 
    string title = DoSomeMagic(predicate, "Title"); 
    if (!string.isNullOrEmpty(id)) 
     ...make ID search 
    else 
     ...search by title 
} 

免責聲明:服務提供者是開往替代今年秋季的傳統點播服務系統,使聯SQL合適的選擇; O)

回答

1

你不能簡單的內省謂語。也許你應該考慮改變你的設計中融入了更多的特設謂詞類型,更具體的謂詞接口:

public interface IDocument 
    { 
     string Id {get; set;} 
     string Title {get; set;} 
    } 
    public class SearchCriteria 
    { 
     public Nullable<int> Id; 
     public string Title; 
    } 
    public IEnumerable<IDocument> Search(SearchCriteria predicate) 
    { 
     if (predicate.Id.HasValue) 
      //...make ID search 
     else if (!string.IsNullOrEmpty(predicate.Title)) 
      //...search by title 
     else 
      // other kind of search 
    } 

與屬性更換公共領域,放在SearchCriteria搜索邏輯(例如.GetResult()或。 GetSQLQuery()),這可能適合您的系統,假設您可以知道所有可用的搜索條件。

+0

這就是我們決定執行表達式去做。我們應該構建的表達式樹會變得非常複雜,因此我們針對謂詞運用了更多的KISS方法。 – kerbou 2010-03-12 10:19:32

3

你不能用謂詞或委託來做到這一點。它們被編譯,並且不可能獲取它返回的信息。你真的需要Expression樹,但你自己解析這可能很困難。你最好使用O/RM工具。

當您使用了一個表達的LINQ到SQL例如,建立你的搜索方法將是一件輕而易舉的事:

public IEnumerable<Document> Search(
    Expression<Func<Document, bool>> predicate) 
{ 
    using (db = new DocumentDataContext()) 
    { 
     return db.Documents.Where(predicate).ToArray(); 
    } 
} 
0

您需要將您的方法聲明爲接受Expression>。這個表達式可以被內省(儘管它有很多不同的東西)。

嘗試運行在LinqPad以下(LinqPad提供了轉儲擴展方法,其形象化的表達真的很好)

void Main() 
{ 
    show(x=>x.Length==5); 
} 

void show(Expression<Predicate<string>> e){ 
    e.Dump(); 
} 

你可以通過調用Compile第一