Тип C # безопасный и удобный для разработчиков список / техника сбора - PullRequest
2 голосов
/ 16 июня 2010

Я заполняю «Словарь» результатами вызова sp.Ключом является имя поля, а значением является любое значение, которое sp возвращает для поля.Это все хорошо, но я бы хотел, чтобы разработчики имели предопределенный список ключей для доступа к этому списку по соображениям безопасности и документации.Я хотел бы иметь что-то вроде enum в качестве ключа для словаря, чтобы разработчики могли безопасно получать доступ к списку, но при этом иметь возможность доступа к словарю со значением строкового ключа.

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

ПРИМЕЧАНИЕ: я бы хотел, чтобы был один ключ, который управляет этимне одно объявление enum и одно объявление List, так как я буду поддерживать два списка ключей, только в слегка отличающихся форматах.

ОБНОВЛЕНИЕ: Позвольте мне уточнить причину, по которой я хочу использовать строковый ключ, который я используюэтот список вещей в одном случае, чтобы сделать замены в большей строке, которая имеет что-то вроде ## keyName ##.Поэтому я должен иметь возможность получить значения из моего словаря на основе того, что в ####.Я не знаю, как это сделать, если я использую enum в качестве ключа.если бы я смог отобразить строку «keyName» в enum.keyName, мои проблемы были бы решены.

Ответы [ 8 ]

3 голосов
/ 16 июня 2010

Я бы просто создал класс, содержащий константные строки вместо перечислений.

class Keys
{
    public const string Key1 = "Key1";
    public const string Key2 = "Key2";
}

Таким образом, вам не нужно ничего делать со словарем, но у вас все еще есть «предлагаемые ключи».

1 голос
/ 16 июня 2010

Похоже, вы пытаетесь повторить функциональность, уже присутствующую в типизированных наборах данных, LINQ to SQL или даже просто старых DTO (возможно, с некоторой помощью Automapper).Разработчикам будет легче работать с уже знакомыми конструкциями, такими как таблицы данных или свойства объектов

1 голос
/ 16 июня 2010

Если вы не ищете много накладных расходов, тогда можно использовать методы Extension.

1 голос
/ 16 июня 2010

Любое перечисление может быть преобразовано в строку с помощью ToString.Следовательно, вы можете написать индексатор, который принимает любой объект и вызывает ToString для него.Для строки это не работает.

edit

Чтобы украсть идею у meiscooldude:

public static class EnumDictExt
{
    public static TValue Lookup<TValue, TEnum>(this IDictionary<string, TValue> dict, TEnum e)
            where TEnum : struct, IComparable, IFormattable, IConvertible
        { return dict[e.ToString()]; }
}
0 голосов
/ 16 июня 2010

Если я вас правильно понимаю, я недавно сделал нечто подобное с пакетами, которые я получил / отправил на сервер. Пакеты были в форме Key: Value\n и определялись специальной парой ключ / значение, обозначающей тип ее пакета (Action: Login, в данном случае ниже. Для получения дополнительной информации см. Asterisk API ). Я проанализировал пакет наберите сгенерированные классы на основе ожидаемых ключей, как таковые:

public abstract class Packet
{
    private Dictionary<string, string> _dictionary =
        new Dictionary<string, string>();

    public string this[string key]
    {
        get
        {
            if (_dictionary.ContainsKey(key))
            {
                return _dictionary[key];
            }
            else { return ""; }
        }
        set { _dictionary[key] = value; }
    }

    public abstract PacketType Type { get; }
}

public class LoginPacket : Packet
{
    public override PacketType Type
    { get { return PacketType.Action; } }

    public string Username
    {
        get { return this["Username"]; }
        set { this["Username"] = value; }
    }
    public string Password
    {
        get { return this["Password"]; }
        set { this["Password"] = value; }
    }
    public int Status // Example: Not an actual key in Login in the Asterisk API
    {
        get { return int.Parse(this["Status"]); }
        set { this["Status"] = value.ToString(); }
    }
}

Это создает своего рода строго типизированный словарь, и вы можете сделать:

LoginPacket packet = new LoginPacket
{
    Username = "User",
    Password = "user",
    Status = 123
};
Console.WriteLine(packet.Username); // Is equal to:
Console.WriteLine(packet["Username"]);

Затем обработайте packet, как и любой другой словарь-подобный класс. Вы можете расширить это так, чтобы Packet реализовал IDictionary, или пойти в другом направлении и сделать this[string key] get или set защищенным, чтобы используются только действительные ключи.

0 голосов
/ 16 июня 2010

Как уже говорили другие, вы можете создать два индексатора. Но чтобы поощрить перечисление и препятствовать созданию строки, сделайте перечисление индексатором и назовите строку api как «GetTheValueOfThisElementWhichCanBeUnsafe» или подобное (вы понимаете ...).

Я ленив, если оба являются индексаторами, мне было бы все равно, но я все время использую строковую версию. Но если API лает на меня определенным образом, я, по крайней мере, вижу последствия в коде.

0 голосов
/ 16 июня 2010

Вы можете попробовать что-то вроде следующего:

public enum MyKeys
{
    FirstKey,
    SecondKey,
    ThirdKey
}

И затем в другом месте вашего кода:

var dict = new Dictionary<MyKeys, string>();

dict.Add(MyKeys.FirstKey, "something");
dict.Add(MyKeys.SecondKey, "something else");
dict.Add(MyKeys.ThirdKey, "something else again");

// And then to access them, you can use
var stringVal = dict[MyKeys.FirstKey];
var secondVal = dict[(MyKeys)Enum.Parse(typeof(MyKeys), "secondkey", true)];
0 голосов
/ 16 июня 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...