【C#】【dynamic】クラスを定義せず実行時にオブジェクトに役割を与える。

  • 2011.05.13 Friday
  • 22:55
JUGEMテーマ:コンピュータ


あいわからずDictionary<T, K>をラップしたDynamicObjecctを使用してプログラミングを
してみたぞ(遊んでみた)という内容を投稿したいと思います。

今日、作ろうと思うのは下記のような構造をもつオブジェクトです。



クラスを定義せずに、プログラミングをしようとした場合に
一番に考えたのが、このようなオブジェクト図(もどき)でした。
上記は4つのノードを追加した状況にある場合のスナップショットです。

これにたいしてクライアント(ProgramクラスのMainの処理)は
今回は2つのメッセージを送りたいと思っています。

1. 値を追加する
2. 列挙する

Mainの処理を書いてみると

    static void Main(string[] args)
    {
      dynamic list = CreateList();
      list.Add(1);
      list.Add(2);
      list.Add(3);

      foreach (int value in list.GetEnumerable())
      {
        Console.WriteLine(value);
      }
    }

このコードがは私の希望です。
前回までは、下記のように書いてました。

    static void Main(string[] args)
    {
      dynamic list = CreateList();
      Add(list, 1);
      Add(list, 2);
      Add(list, 3);

      foreach (int value in GetEnumerable(list))
      {
        Console.WriteLine(value);
      }
    }

listオブジェクトにメッセージを送りたいので
なるべくなら

Add(list, 1);

ではなく

list.Add(1);

と記述したいわけです。要するにカリー化したいんです(←よくわからない言葉を使うのは気がひけます)

list.Method(...)と記述するといかにもオブジェクトがもつメソッドを呼び出したように見えます。



是非とも記述したい。
そこで、今回は一工夫いれながらコードを書いてみました。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;

namespace Art55.DynamicNamedPropertyObjectDemo001
{
  class Program
  {
    static void Main()
    {
      dynamic list = CreateList();
      list.Add(1);
      list.Add(2);
      list.Add(3);

      foreach (int value in list.GetEnumerable())
      {
        Console.WriteLine(value);
      }
    }

    static dynamic CreateList()
    {
      dynamic list = NamedDynamicObject.Create();
      list.First = null;
      list.Last = null;
      list.Add = new Action<object>(value => Add(list, value));
      list.GetEnumerable = new Func<IEnumerable>(() => GetEnumerable(list));
      return list;
    }

    static void Add(dynamic list, object value)
    {
      dynamic node = CreateListNode(value);
      if (list.First == null)
        list.First = list.Last = node;
      else
        list.Last = list.Last.Next = node;
    }

    static IEnumerable GetEnumerable(dynamic list)
    {
      for (dynamic currentNode = list.First; currentNode != null; currentNode = currentNode.Next)
      {
        yield return currentNode.Value;
      }
    }

    static dynamic CreateListNode(object value)
    {
      dynamic node = NamedDynamicObject.Create();
      node.Value = value;
      node.Next = null;
      return node;
    }
  }

  public class NamedDynamicObject : DynamicObject
  {
    public static dynamic Create()
    {
      return new NamedDynamicObject();
    }

    protected NamedDynamicObject()
    {
      _setting = new Dictionary<string, object>();
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
      return _setting.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
      _setting[binder.Name] = value;
      return true;
    }

    private readonly Dictionary<string, object> _setting;
  }
}

CreateList()メソッドでListの能力を全て構築させます。こうすることで、CreateListの戻り値のオブジェクトはすでにListな振る舞いをするオブジェクトとなっているわけです。CreateList()
メソッドが呼ばれたあとの処理は、全てlistにたいしてメッセージを送るだけで、要求が満たされるようになるわけです。こうすることでListオブジェクトが管理しているListNode達の存在や構造を意識することもなくりました。

心残りは

list.Add = new Action<object>((value) => Add(list, value));

こういうのが、もう少しわかりやすくかけないかなーってところです。

以上


---------------------
クラスに書き換えたヴァージョン

  class Program
  {
    static void Main()
    {
      var list = new List();
      list.Add(1);
      list.Add(2);
      list.Add(3);

      foreach (int value in list.GetEnumerable())
      {
        Console.WriteLine(value);
      }
    }
  }

  public class List // : IEnumerable
  {
    private ListNode _first;
    private ListNode _last;

    public void Add(object value)
    {
      dynamic node = new ListNode {Value = value};
      if (_first == null)
        _first = _last = node;
      else
        _last = _last.Next = node;
    }

    public IEnumerable GetEnumerable()
    {
      for (ListNode currentNode = _first; currentNode != null; currentNode = currentNode.Next)
      {
        yield return currentNode.Value;
      }
    }

    class ListNode
    {
      public object Value { get; set; }
      public ListNode Next { get; set; }
    }

    //public IEnumerator GetEnumerator()
    //{
    //  return GetEnumerable().GetEnumerator();
    //}
  }

コメント
コメントする








    
この記事のトラックバックURL
トラックバック

calendar

S M T W T F S
  12345
6789101112
13141516171819
20212223242526
2728293031  
<< January 2019 >>

あわせて読みたい

あわせて読みたいブログパーツ

selected entries

categories

archives

recent comment

  • 【キーボード】6年前のRealForceを復活させることはできる!?その3
    art55 (05/22)
  • 【キーボード】6年前のRealForceを復活させることはできる!?その3
    分解大好き (05/18)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    art55 (02/04)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    Gen (02/04)
  • 【キーボード】RealForce が壊れて帰ってきた。
    art55 (04/29)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    art55 (02/23)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    かるあ (02/22)
  • 【C#】Dictionaryの実装・データ構造・アルゴリズムを観察する。
    art55 (01/16)
  • 【C#】Dictionaryの実装・データ構造・アルゴリズムを観察する。
    karuakun (01/16)
  • 【NetOffice】【Excel】死なないExcelプロセスをKillする。
    art55 (12/05)

recent trackback

recommend

recommend

recommend

C#プログラマのための.NETアプリケーション最適化技法 (Programmer's SELECTION)
C#プログラマのための.NETアプリケーション最適化技法 (Programmer's SELECTION) (JUGEMレビュー »)
Sasha Goldshtein,Dima Zurbalev,Ido Flatow,サシャ・ゴルドシュタイン,ディマ・ズルバレフ,イド・フラトー

recommend

ろんりと集合
ろんりと集合 (JUGEMレビュー »)
中内 伸光
とてもわかりやすいです。

recommend

recommend

シャノン・ノイマン・ディジタル世界
シャノン・ノイマン・ディジタル世界 (JUGEMレビュー »)
市川 忠男
4章がリレーショナルデータベースな内容になってます。ページ数があまりありませんが、ポイントがものすごく的確にまとまっていて、感動します。

recommend

recommend

東プレ Realforce91UBK-S 静音キーボード 静電容量無接点方式 変荷重 ブラック NG01BS
東プレ Realforce91UBK-S 静音キーボード 静電容量無接点方式 変荷重 ブラック NG01BS (JUGEMレビュー »)

テンキーレス、静音のRealForce91UBK-S。スコスコ感がたまらなく気持ちいいです。家と会社で2台持ってます。

recommend

recommend

プログラミング.NET Framework 第4版 (プログラミングシリーズ)
プログラミング.NET Framework 第4版 (プログラミングシリーズ) (JUGEMレビュー »)
Jeffrey Richter
発売予定美 2013年10月10日。.NET Frameworkとお付き合いする人のバイブルですね。

recommend

recommend

キャット・シッターの君に。
キャット・シッターの君に。 (JUGEMレビュー »)
喜多嶋 隆
私のイラストレータデビュー本です。

recommend

Essential .NET ― 共通言語ランタイムの本質
Essential .NET ― 共通言語ランタイムの本質 (JUGEMレビュー »)
ドン・ボックス,クリス・セルズ,Don Box,Chris Sells,吉松 史彰

links

profile

search this site.

others

mobile

qrcode

powered

無料ブログ作成サービス JUGEM