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
動的オブジェクトの作成時にコンストラクターによって設定され、直後の最後の参照ディクショナリとして設定されます。これは、 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
、私はそれを必要としなかったので追加しませんでした。