您可以通过在TryGetValue
调用时存储对先前检索到的对象或字典的引用来做到这一点。我使用如下所示的类:
public DynamicFile(IDictionary<string, object> dictionary)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
_dictionary = dictionary;
_lastGetRef = _dictionary;
}
private readonly IDictionary<string, object> _dictionary;
private IDictionary<string, object> _lastGetRef;
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (!_dictionary.TryGetValue(binder.Name, out result))
{
result = null;
return true;
}
var dictionary = result as IDictionary<string, object>;
if (dictionary != null)
{
result = new DynamicFile(dictionary);
_lastGetRef = dictionary;
return true;
}
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if(_dictionary.ContainsKey(binder.Name))
_dictionary[binder.Name] = value;
else if (_lastGetRef.ContainsKey(binder.Name))
_lastGetRef[binder.Name] = value;
else
_lastGetRef.Add(binder.Name, value);
return true;
}
_dictionary
由构造函数在创建动态对象时设置,然后设置为直接最后一个引用字典。这是因为字典是类,因此是引用类型。
为了正确嵌套,您需要在每个嵌套级别实例化每个字典,就像多维数组一样。例如:
myexpando.somelist = new Dictionary<string, object>();
myexpando.somelist.anotherlist = new Dictionary<string, object>();
myexpando.somelist.anotherlist.someitem = "Hey Hey There! I'm a nested value :D";
您可能可以编写一些代码,TryGetMember
当密钥不存在时自动添加字典,但我不需要,所以我没有添加它。