LoginSignup
5

More than 3 years have passed since last update.

[C#]型によって処理をグループ化する

Last updated at Posted at 2019-04-21

概要

自作クラス(型)によって処理を分ける。

クラス構成

  • **Actionクラス
    • 処理の単位になる型。処理に必要な固有情報を持ってる。
  • Dispatcherクラス
    • 処理をためるシングルトンクラス。
  • TODOStoreクラス
    • **Actionクラスごとに実行する処理を設定する。

サンプル

アクションクラス

    public class CreateItemAction
    {
        public CreateItemAction(string message)
        {
            Message = message;
        }

        public string Message { get; private set; }
    }
    public class WriteItemAction { }
    public class IntAction
    {
        public IntAction(int id) => this.id = id;
        public int id;
    }

これらをDispatcherクラスに渡すとDispatcherクラスが型によって処理を分けて実行してくれる。

  • CreateItemActionクラスはItemを作成する処理をする型
  • WriteItemActionクラスは画面にItemを表示する型
  • IntActionクラスはIdを指定してItemを作成する型

dispatcherクラス

   class Dispatcher
    {
        //singleton
        private static readonly Dispatcher disp = new Dispatcher();
        public static Dispatcher Instance => disp;
        private Dispatcher() { }

        Dictionary<Type, IList<object>> dic = new Dictionary<Type, IList<object>>();
        public void Resist<T>(Action<T> a)
        {
            var key = typeof(T);
            if (!dic.ContainsKey(key)) dic.Add(key, new List<object>());
            dic[key].Add(a);
        }

        public void Dispatch<T>(T payload)
        {
            var key = typeof(T);
            if (!dic.ContainsKey(key)) return;

            dic[key].OfType<Action<T>>()
                    .ToList()
                    .ForEach(call => call(payload));
        }
    }

Resistは型ごとに処理をためるメソッド。
Dispatchは型ごとに処理を実行するメソッド。

TODOStoreクラス

    class TODOStore
    {
        public Dispatcher AppDispatcher { get; private set; } = Dispatcher.Instance;
        private Dictionary<string, TODOItem> items = new Dictionary<string, TODOItem>();
        private readonly Random random = new Random();

        public TODOStore()
        {
            AppDispatcher.Resist<CreateItemAction>(
                c =>
                {
                    var newText = c.Message;
                    if (string.IsNullOrWhiteSpace(newText)) return;
                    Create(newText);
                }
            );
            AppDispatcher.Resist<WriteItemAction>(
                c =>
                {
                    PrintItem();
                }
            );
            AppDispatcher.Resist<IntAction>(
                c =>
                {
                    var id = c.id;
                    if (id == 0) return;
                    Create(id);
                }
            );
        }
        void Create(string newText)
        {
            var now = DateTime.Now;
            var offset = Math.Floor(((random.NextDouble() + random.NextDouble()) / 2) * 999999);

            var id = $"{now}-{offset}";
            var item = new TODOItem
            {
                Text = newText,
                Id = id,
            };

            items[id] = item;
        }
        void Create(int id)
        {
            var item = new TODOItem
            {
                Text = "default",
                Id = id.ToString(),
            };
            items[id.ToString()] = item;
        }
        void PrintItem()
        {
            foreach (var i in items)
            {
                WriteLine($"{i.Value.Id}  {i.Value.Text}");
            }
        }
    }

TODOStoreクラスは実際の処理を指定するクラス。
コンストラクターでそれぞれのActionクラスごとに何をするかを定義する。
IntActionの場合、Idが被っていると上書きされる。

使う側

        static void Main(string[] args)
        {
            string[] mes = { "new-Item1", "new-Item2", "new-Item3", };
            new TODOStore();
            var ia = new IntAction(1);
            CreateItemAction[] cia =
            {
                new CreateItemAction(mes[0]),
                new CreateItemAction(mes[1]),
                new CreateItemAction(mes[2]),
            };

            var writeAction = new WriteItemAction();

            Dispatcher.Instance.Dispatch(cia[0]);
            Dispatcher.Instance.Dispatch(cia[1]);
            Dispatcher.Instance.Dispatch(cia[2]);
            Dispatcher.Instance.Dispatch(ia);
            Dispatcher.Instance.Dispatch(ia);
            Dispatcher.Instance.Dispatch(writeAction);
        }

これを実行すると
image.png

こうなる。

その他

Fluxパターンについて調べていたところ、GUI以外も使いどころありそうと思ったのでメモ。
shiftkeyさんのリポジトリが神。https://github.com/shiftkey/fluxsharp-proof-of-concept

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5