Проблема с перечислением как ключ в наборе Словаря

У меня есть сценарий, где я использую Словарь для содержания списка типов транзакции, которые принимает определенная система. Ключ в Словаре является перечислимым полем, значение является интервалом.

В какой-то момент в системе, мы собираемся хотеть сделать что-то вроде этого:

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

Когда мы ищем поле в словаре, мы собираемся заставить корректное целочисленное значение питаться к базе данных. Я думал о фактическом использовании перечислимого международного значения для этого, но это не точно правильно. Мы взаимодействуем с системой, где мы должны подать магическое число в представить вид обновления, мы делаем.

Код выше работает просто великолепно. У меня есть метод инициализатора, который добавляет известные типы:

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? Но я не использую автоматически сгенерированный прокси... оба проекта с обеих сторон провода совместно используют типы как ссылку проекта, и я создаю свой клиент канала в коде.

Какие-либо идеи? Я делаю его неправильно? Словари с Перечислениями, поскольку ключи не работают хорошо? Действительно ли это - вещь WCF?

Примечание: спасибо за предложения относительно установки перечислений для содержания волшебного интервала. Я хотел установить тех, которые в конфигурации, однако, как его возможное, которое "магические числа" 4 5 и 6 могли бы изменить в будущем. Таким образом, если я кодирую их в к перечислению, как предложено:

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

Я теряю способность записать метод, который настраивает магические числа в будущем во время выполнения; вместо этого это потребовало бы изменения кода.

5
задан Kyle Hodgson 5 March 2010 в 20:44
поделиться

4 ответа

Вместо использования перечисления в качестве ключа используйте целочисленное представление перечисление.

Например:

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

3
ответ дан 15 December 2019 в 00:58
поделиться

Вам вообще не нужна таблица поиска:

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
1
ответ дан 15 December 2019 в 00:58
поделиться

Вы можете явно установить значения перечисления, используя синтаксис

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);
0
ответ дан 15 December 2019 в 00:58
поделиться

Можете ли вы подумать о том, чтобы набирать ваше перечисление явно как int (или как бы то ни было type is), а затем установить значение каждого из ваших перечислений на значение базы данных? Вы уже тесно связали перечисление с базой данных, поэтому связь будет определяться либо на C # (текущее жесткое кодирование), либо на SQL (возможно, процедура, которая возвращает идентификатор, а также строку, которая может быть проанализирована в перечисление. .)

Используя предположение, что ваше перечисление является int ...

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

При добавлении параметра вы просто приводите его к типу, лежащему в основе перечисления.

sqlCommand.Parameters.AddWithValue("@param", (int)argument.enumField);
0
ответ дан 15 December 2019 в 00:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: