2010-03-05 92 views
5

我有一個場景,我使用字典來保存特定系統接受的事務類型列表。 Dictionary中的鍵是一個枚舉字段,其值是一個int。枚舉作爲字典集合中的鍵時遇到問題

在系統中的某個時刻,我們要想要做這樣的事情:

sqlCommand.Parameters.AddWithValue("@param", LookupDictionary[argument.enumField]); 

當我們仰望領域的字典,我們要得到正確的整數值提供給數據庫。我曾想過爲此使用enum int值,但這不完全正確。我們正在與一個系統進行交互,我們需要提供一個神奇數字來表示我們正在進行的更新。

上面的代碼工作得很好。我有一個初始化方法添加已知類型:

LookupDictionary = new Dictionary<mynamespace.myproject.myclass.enumType, int>(); 
LookupDictionary.Add(enumType.entry1, 4); 
LookupDictionary.Add(enumType.entry2, 5); 
LookupDictionary.Add(enumType.entry3, 6); 

此代碼也正常工作。

但是,在我真正開始使用LookupDictionary之前,我驗證了所做的請求實際上已設置爲我們支持的枚舉值。這是LookupDictionary的主要原因,它保存有效的(有有效的枚舉條目,這種方法不起作用)。

這是不起作用的代碼:系統無法識別枚舉匹配。在調試器中,我可以看到LookupDictionary中的條目列表確實顯示它具有entry2的值 - 它只是將它稱爲entry2。另一方面,傳入的enumField具有完整的名稱空間; mynamespace.myproject.myclass.enumType.entry2 - 我想這就是爲什麼它沒有看到它們是相同的。

if (!LookupDictionary.ContainsKey(argument.enumField)) 
{ 
    throw new InvalidOperationException("argument.enumField not valid in blahMethod."); 
} 

我是否提到過這是通過WCF服務傳遞的?但是我沒有使用自動生成的代理...線路兩側的兩個項目都將這些類型作爲項目引用共享,並且我使用代碼構建了我的通道客戶端。

任何想法?我做錯了嗎?使用Enums作爲密鑰的字典無法正常工作?這是一個WCF的東西嗎?

注意:感謝您的建議有關設置枚舉最多包含magic int。然而,我想把它們設置成一個配置,因爲它有可能「幻數」4,5和6可能會改變。所以,如果我到枚舉代碼,他們的建議:

public enum MyEnum 
{ 
    MyValue1 = 4, 
    MyValue2 = 5, 
    MyValue3 = 6 
} 

我輸寫在運行時也設定在未來的幻數的方法的能力;相反,它需要更改代碼。

+3

字典與枚舉類型沒有問題,我懷疑它與WCF有關。這裏只有很少的代碼片段 - 一個簡短但完整的程序重現了這個問題可能會帶來一些答案。從最簡單的情況開始 - 將一個枚舉鍵添加到字典中,並驗證它是否存在。然後逐漸建立起來,直到你碰到你的代碼失敗的地方。 – Aaronaught 2010-03-05 01:33:39

+0

我相信你是對的。我有一種強烈的感覺,我在某處遇到了一些小錯誤;只是以爲我會把它扔到那裏。至少有一位我認識的WCF人士認爲它可能是自動生成的代理,這就是爲什麼我基於DataContracts的共享項目重新組織的原因。一切都很順利,但並沒有解決問題。 – 2010-03-05 19:47:52

回答

3

代替使用枚舉作爲關鍵的,可以使用枚舉的整數表示。

例如:

LookupDictionary = new Dictionary<int, int>(); 
LookupDictionary.Add((int)enumType.entry1, 4); 
LookupDictionary.Add((int)enumType.entry2, 5); 
LookupDictionary.Add((int)enumType.entry3, 6); 

這樣的話,你可以使用字典一樣 '的containsKey' 方法。我不確定這是一個好的表現嗎?List<int>

+0

恩,謝謝...我喜歡這個......去試試看。應該給我與我想要的相同的可維護性,並保留稍後從配置中重寫它的能力。 – 2010-03-05 20:45:35

+0

工作!仍然不知道發生了什麼......還有其他一些域名被傳遞給了這個服務,但這些域名並沒有「正常」通過,所以我懷疑是否有其他問題。但是這解決了我的問題。謝謝! – 2010-03-05 21:26:36

0

你可以考慮明確地鍵入你的枚舉爲int(或任何基礎類型),然後將每個枚舉的值設置爲數據庫值嗎?您已經將枚舉與數據庫緊密耦合,因此無論是使用C#(當前硬編碼)還是通過SQL(可能是返回ID的proc以及可以解析爲枚舉的字符串。)

使用,前提是你的枚舉是一個int ...

enum enumType { 
    entry1 = 4, 
    entry2 = 5, 
    entry3 = 6 
} 

當添加那麼你就只投作爲枚舉的基礎類型的參數。

sqlCommand.Parameters.AddWithValue("@param", (int)argument.enumField); 
+0

枚舉的存在表示數據庫中的有效值,緊密耦合不成問題。問題是我希望能夠在運行時生成正確的「幻數」,以防它們發生變化。如果我像你指定的那樣設置它們,entry1 = 4,我不能在它周圍包裹一個循環。實際值不會改變,只是它們的int表示可能。例如,entry1今天可能是4,但一週可能是40。 Lookup.Add允許我稍後編寫一個方法,並從數據庫中提取正確的魔術值並將它們存儲在查找字典中。 – 2010-03-06 17:08:45

1

你不應該需要一個查找表,在這裏所有:

public enum MyEnum 
{ 
    MyValue1 = 4, 
    MyValue2 = 5, 
    MyValue3 = 6 
} 

// Sample usage 
MyEnum firstEnum = MyEnum.MyValue1; 
int intVal = (int)firstEnum; // results in 4 

// Enum Validation 
bool valid = Enum.IsDefined(typeof(MyEnum), intVal); // results in true 
+0

該枚舉具有此方法無法處理的條目。所以查找的目的是檢查我們是否被請求設置爲我們無法處理的那些類型之一。 – 2010-03-05 22:16:59

0

您可以使用語法

enum ArgumentTypes { 
    Arg1 = 1; 
    Arg2 = 3; 
    Arg3 = 5; 
} 

你並不需要明確設置枚舉值將每個值依次保存在該語法的枚舉中。

要驗證只有對該方法有效的參數可以使用,請嘗試此示例代碼。注意我建議在此上下文中使用ArgumentException而不是InvalidOperationException。

public void DoDbWork(ArgumentTypes argType, object otherParameter) 
{ 
    if (argType == ArgumentTypes.Arg3) { 
     throw new ArgumentException("Argument of value " + argType + " is not valid in this context", "argType"); 
    } 

    // Handle db transaction here 
} 

向該int值添加作爲參數:

cmd.Parameters.AddWithValue("@paramName", (int)argType);