2010-03-05 43 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);