Динамическое использование словаря в C # - PullRequest
3 голосов
/ 22 июля 2010

Я использую динамический словарь в C #. Проблема, с которой я сталкиваюсь, заключается в поведении TryGetMember, которое я переопределяю в классе динамического словаря.

Вот код динамического словаря.

class DynamicDictionary<TValue> : DynamicObject
{
    private IDictionary<string, TValue> m_dictionary;

    public DynamicDictionary(IDictionary<string, TValue> a_dictionary)
    {
        m_dictionary = a_dictionary;
    }

    public override bool TryGetMember(GetMemberBinder a_binder, out object a_result)
    {
        bool returnValue = false;

        var key = a_binder.Name;
        if (m_dictionary.ContainsKey(key))
        {
            a_result = m_dictionary[key];
            returnValue = true;
        }
        else            
            a_result = null;

        return returnValue;
    }
}

Здесь TryGetMember будет вызываться во время выполнения всякий раз, когда мы ссылаемся на какой-либо ключ извне, но странно, что член Name связывателя, который всегда дает ключ, на который мы ссылаемся извне, всегда разрешает имя ключа, записанное в виде букв алфавита.

например. если объект DynamicDictionary выполнен как:

Dictionary<string,List<String>> dictionaryOfStringVsListOfStrings; 

//here listOfStrings some strings list already populated with strings
dictionaryOfStringVsListOfStrings.Add("Test", listOfStrings); 
dynamic dynamicDictionary_01 = new 
    DynamicDictionary<List<String>(dictionaryOfStringVsListOfStrings);

string somekey = "Test";

//will be resolve at runtime
List<String> listOfStringsAsValue = dynamicDictionary_01.somekey 

Теперь, что здесь происходит, «somekey» станет значением a_binder (т.е. a_binder.Name = «somekey»). Он должен быть разрешен как a_binder.Name = "Test", а затем из динамического словаря он найдет listOfStrings для этого ключа (то есть фактически "Test", но он разрешает не значение, а фактическое имя переменной как ключ).

Есть ли способ обойти это?

1 Ответ

5 голосов
/ 22 июля 2010

Смысл динамической типизации состоит в том, чтобы заставить имена самих членов разрешаться из доступа к элементу исходного кода.

Динамическая типизация работает точно так, как и здесь - она ​​не предназначена чтобы получить значение переменной и использовать его в качестве имени члена - он предназначен для использования имени члена, которое вы использовали в своем исходном коде (например, «somekey»).

Звучит так, будто вам действительно не нужнодинамическая типизация вообще здесь - просто используйте Dictionary<string,List<String>> как обычно:

List<String> listOfStringsAsValue = dictionary[somekey];

РЕДАКТИРОВАТЬ: Звучит так, как будто вы действительно хотите инкапсулировать словарь следующим образом:

public class Foo // TODO: Come up with an appropriate name :)
{
    private readonly Dictionary<string, List<string>> dictionary =
        new Dictionary<string, List<string>>();

    public List<string> this[string key]
    {
        get
        {
            List<string> list;
            if (!dictionary.TryGetValue(key, out list))
            {
                list = new List<string>();
                dictionary[key] = list;
            }
            return list;
        }
    }
}

Тогда выdo:

foo["first"].Add("value 1");
foo["second"].Add("value 2")
foo["first"].Add("value 1.1");

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

Это действительно не похоже на то, что вам нужен DynamicObject.

...