いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

.NET クラスライブラリ探訪-068 (System.Dynamic.DynamicObject, 動的オブジェクトの作成)

だいぶ前に

という記事を書いていて、System.Dynamic.ExpandoObjectについては
記述していたのですが、System.Dynamic.DynamicObjectについて記述してなかったなーと思いだして
メモ代わりにアップです。

System.Dynamic.DynamicObjectは、直接インスタンス化できないクラスで
利用する場合は、派生クラスを作成します。
いろいろなメソッドが用意されているのですが、プロパティの動的設定および取得が
目的であれば、

TryGetMember
TrySetMember

の2つのメソッドをオーバーライドすれば事足ります。

以下、サンプルです。

namespace Sazare.Samples
{
  using System;
  using System.Collections.Generic;
  using System.Dynamic;
  using System.Linq;
  
  using Sazare.Common;

  /// <summary>
  /// System.Dynamic.DynamicObjectについてのサンプルです。
  /// </summary>
  [Sample]
  class DynamicObjectSamples01 : IExecutable
  {
    public void Execute()
    {
      //
      // DynamicObjectクラスのサブクラスを作成する
      // ことで、簡単にdynamic対応のクラスを作成することが
      // できる。実際、DynamicObjectの中には多くのメソッドが
      // 定義されているが、動的な値を格納するようにするだけであれば
      //   TryGetMember
      //   TrySetMember
      // メソッドをオーバーライドすれば事足りる。
      //
      dynamic obj = new MyDynamicObject();

      obj.age  = 100;
      obj.name = "name1";

      Output.WriteLine(obj.GetType().Name);
      Output.WriteLine(obj.AGE);
      Output.WriteLine(obj.NAME);
    }

    class MyDynamicObject : DynamicObject
    {
      readonly Dictionary<string, object> _memberMappings;

      public MyDynamicObject()
      {
        _memberMappings = new Dictionary<string, object>();
      }

      public override bool TryGetMember(GetMemberBinder binder, out object result)
      {
        result = null;

        var name = binder.Name.ToUpper();
        if (_memberMappings.ContainsKey(name))
        {
          result = _memberMappings[name];
          return true;
        }

        return false;
      }

      public override bool TrySetMember(SetMemberBinder binder, object value)
      {
        var name = binder.Name.ToUpper();
        if (_memberMappings.ContainsKey(name))
        {
          _memberMappings[name] = value;
        }
        else
        {
          _memberMappings.Add(name, value);
        }

        return true;
      }
    }
  }
}

実行すると以下のようになります。

================== START ==================
MyDynamicObject
100
name1
==================  END  ==================

以下、参考資料です。


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。