2010-03-28 67 views
0

我有下面的類:動態的LINQ庫幫助

public class Item 
{ 
    public Dictionary<string, string> Data 
    { 
     get; 
     set; 
    } 
} 

和它的一個列表:

List<Item> items; 

我需要動態篩選和爲了這個列表使用類似SQL的字符串。問題在於,我需要通過數據字典對其進行排序。例如:Order By Data["lastname"]Where Data["Name"].StartsWith("a")。我想使用動態LINQ庫,但有沒有什麼辦法讓我的客戶可以在沒有Data []的情況下編寫?比如:

Name.StartsWith("abc") 

代替

Data["Name"].StartsWith("abc") 

+0

嗯...一個擴展類可能有幫助...這個想法是你隱藏真正的實現並提供一個更簡單的代理。名稱必須是知道數據的類。 – 2010-03-28 14:24:31

回答

1

你可以添加這樣一個屬性:

public class Item 
{ 
    public Dictionary<string, string> Data 
    { get; set; } 

    public string Name { get { return Data["lastname"]; } } 
} 
//Call by: i.Name.StartsWith("abc"); 

或擴展方法:

public static class ItemExtensions 
{ 
    public static string Name(this Item item) 
    { 
    return item.Data["lastname"]; 
    } 
} 
//Call by: i.Name().StartsWith("abc"); 

或者,如果它是一個非常常用的方法,你可以添加一些像.NameStartsWith()

public static string NameStartsWith(this Item item, stirng start) 
{ 
    return item.Data["lastname"].StartsWith(start); 
} 
//Call by: i.NameStartsWith("abc"); 
+0

不,我不能。這就是我問這個問題的原因 – 2010-03-28 16:06:30

+0

@Alon - 這是3個不同的選項,最後2個不依賴於在第一個選項中添加屬性。除了動態的4.0或反射,沒有非索引的方式來做到這一點,這就是你問的問題:) – 2010-03-28 16:42:04

+0

「不,我不能。」?就像Nick說的那樣,這些是C#允許您在描述的場景中使用的3個有效選項。如果他們因爲某種原因不能工作,或許你應該提供更多的背景知道爲什麼。 – 2010-03-28 17:32:09

0

I假設你在編譯時不知道屬性的名字(在這種情況下,你可以簡單地定義屬性並且不會有這個問題)。我有兩個建議,你可以嘗試,但我沒有實現它們中的任何一個,所以我不能保證它會工作。

  • 如果你可以使用.NET 4.0,你可以從DynamicObject繼承和(當你被聲明爲dynamic對象上使用o.Foo被稱爲)實現TryGetMember方法。假設動態LINQ與DLR協同工作,它應該爲從DynamicObject繼承的對象自動調用此方法。在TryGetMember方法內部,您將獲得所訪問屬性的名稱,以便您可以執行字典查找。 (但是,只有動態LINQ與DLR集成良好時,此解決方案才能正常工作)。

  • 在任何情況下,您都可以對用戶輸入的字符串進行一些基本的分析,並將Name替換爲Data["Name"]。這肯定會起作用,但它可能有點困難(因爲你至少應該檢查你是否在正確的上下文中進行替換 - 例如不在字符串常量內)。

關於擴展方法 - 我不知道,如果動態LINQ處理擴展方法(但是,我不這麼認爲,因爲這將需要搜索所有引用的程序集)

1

這並不一定與Linq Dynamic Query單元有關的任何事情。該單位適用於當您有實際字段/屬性,並且它們的名稱將在運行時給予您。換句話說,你有一個這樣的類:

public class Person 
{ 
    public int ID { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

而且你希望能夠寫出這樣的查詢:

var sortedPeople = people.OrderBy("FirstName"); 

你正在嘗試做的的完全相反 - 你有一個沒有任何實際屬性的類,只是一個屬性字典,並且你希望編譯時安全。你不能擁有它;如果字典是公開的並且任何人都可以直接添加/刪除,則無法保證該字典中將包含該項目,尤其是

如果有,你必須使用特定一流的設計,那麼你就可以想見,寫一些包裝尼克已經提出了一些原因,但我不會甚至不屑 - 他們實際上並沒有提供任何封裝,因爲Data字典仍然向全世界開放。相反,我只是提供一個單獨的getter方法或索引器屬性,並使用您期望在其中的屬性名稱創建一些常量(或枚舉)。

public class Item 
{ 
    public Dictionary<string, string> Data { get; set; } 

    public string GetValue(string key) 
    { 
     if (Data == null) 
      return null; 
     string result; 
     Data.TryGetValue(key, out result); 
     return result; 
    } 
} 

public class ItemKeys 
{ 
    public const string Name = "Name"; 
    public const string Foo = "Foo"; 
} 

等等。真的ItemKeys並不重要,安全GetValue方法是什麼是重要的,因爲否則你運行的NullReferenceException如果Data尚未分配的風險,或KeyNotFoundException如果甚至一個Item實例沒有該屬性。使用GetValue方法在這裏一定會成功不管是什麼:

var myItems = items.OrderBy(i => i.GetValue(ItemKeys.Name)); 

如果你發現你寫了很多重複的代碼相同的屬性,然後開始擔心添加快捷方式的屬性或擴展方法的類。