C#中的动态字典用法

时间:2010-07-22 13:13:32

标签: c# .net dynamic dictionary

我在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,但奇怪的是,binder的Name成员总是给出我们从外面引用的键,它总是解析写为字母字符的键名。 / p>

e.g。如果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 个答案:

答案 0 :(得分:5)

动态类型的关键是使成员名称本身从源代码成员访问中解析出来。

动态类型的工作方式正如它所指的那样 - 它不是设计的来检索变量的值并将其用作成员名称 - 它旨在使用您在其中使用的成员名称源代码(即“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;
        }
    }
}

然后你可以这样做:

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

如果您希望能够尝试获取列表而不创建新列表(如果它不存在),您可以添加一个方法来执行此操作。

这听起来好像你不需要动态对象。