2010-12-13 35 views
3

如何在字典中使用某種類型的表達式>作爲關鍵字?使用表達式<Func<object>>作爲字典中的關鍵字

我剛開始玩表達式實例,不知道我想做什麼是可能的。

看起來2個相同的表達式與我嘗試時不相同我可以使用表達式作爲鍵將條目放入字典中,但當我詢問字典是否包含鍵時,它將返回false,除非我使用非常相同的表情實例。

TypeToTest test = new TypeToTest(); 
Expression<Func<object>> expression =()=>test.PropertyA; 
IDictionary<Expression<Func<object>>,bool> dictionary = new Dictionary<Expression<Func<object>>, bool>(); 
dictionary[expression] = true; 
Assert.That (dictionary.ContainsKey(expression), Is.True); 
Assert.That (dictionary.ContainsKey(()=>test.PropertyA), Is.True); 

上面的最後一行失敗,當我希望它成功。

意圖是有能力定義一組適用於對象的屬性或方法的規則,以便我可以確定(例如)某個屬性是可編輯的還是具有字典中特定鍵的值可以刪除。我不希望在對象上有一個標誌確定它是否可編輯(因爲可編輯性對於不同的屬性可能不同),另一個標誌確定它是否可刪除,而是另一個負責維護關聯規則的類與對象一起使用,以便在未來擴展對象時,可以添加更多規則來描述對象組成部分的可編輯性/可訪問性/可刪除性/。如果這是有道理的。

有類似的帖子here,但這似乎是基於屬性名稱的關鍵,因爲我希望能夠鍵入方法和參數,所以我可以支持確定持有對象的可編輯性在基於密鑰的字典中。

會這樣的事情是可能的還是它在天空中餡餅?

回答

4

這是比較不同參考時的預期行爲,其中該類型不會覆蓋Equals或實施IEquatable<T>。你可能寫一個自定義比較器(可能只是比較ToString())並將其傳遞到字典 - 但IMO和Expression不是一個很好的選擇的關鍵。

以下是不一定是通過ToString();在使用自己的判斷:

class Program { 
    static void Main() { 
     TypeToTest test = new TypeToTest(); 
     Expression<Func<object>> expression =() => test.PropertyA; 
     IDictionary<Expression<Func<object>>, bool> dictionary = 
      new Dictionary<Expression<Func<object>>, bool>(
       new ToStringComparer<Expression<Func<object>>>()); 
     dictionary[expression] = true; 

     bool x = dictionary.ContainsKey(expression), // true 
      y = dictionary.ContainsKey(() => test.PropertyA); // true 
    } 
} 
class ToStringComparer<T> : IEqualityComparer<T> where T : class { 
    public bool Equals(T x, T y) { 
     if ((x == null && y == null) || ReferenceEquals(x,y)) return true; 
     if (x == null || y == null) return false; 
     return x.ToString() == y.ToString(); 
    } 
    public int GetHashCode(T obj) { 
     return obj == null ? 0 : obj.ToString().GetHashCode(); 
    } 
} 
+0

你爲什麼認爲它不是一個很好的選擇?它似乎允許每個屬性/方法單獨控制其可訪問性,如果類型被擴展(可以使用另一個接口) – 2010-12-13 11:43:09

+0

@Sam - 因爲沒有明確定義的相等性檢查,所以可以輕鬆地擴充該類型。例如;是'x => x.A'與'y => y.A'有相同的表達式嗎?如果表達式捕獲一個捕獲變量包裝的對象實例會怎麼樣? – 2010-12-13 11:44:10

+0

很好的解決方案。 – IamStalker 2014-04-22 12:09:00

2

Expression類型的子類不重寫EqualsGetHashCode方法,使他們也很難使用字典鍵。您的字典使用引用相等性,並且()=>test.PropertyA的兩次出現產生兩個不同的表達式樹對象。

您可以編寫自己的IEqualityComparer<Expression>實現,並將其傳遞到字典構造函數中。在你的比較器中,你可以編寫EqualsGetHashCode方法來處理每個Expression類並比較它們的屬性。

+0

'Expression'覆蓋'GetHashCode',因此'IEqualityComparer '實現可能能夠委託實現(只檢查相同的實例是否給出相同的哈希碼)。 – Richard 2010-12-13 14:51:14

相關問題