C#
.NET
event

カスタムEventArgs

イベントで任意の変数を渡すとき、その都度EventArgsを継承するのが面倒なのでEventArgsをジェネリック片引数を持つオブジェクト継承汎用性を持たせるようにします。

C#はほぼ独学で学習しました、もし認識が誤っているところなどがあれば、ご指摘お願いします。

12/22 ちょこっと変えてみました。
12/27 ちょこっと変えてみました。ご指摘のあった部分を改良しました。

基底クラス系のクラス名AtepからはじまるAtep とは、新たに発見した万能 細胞 関数 Arbitary-Triggered Eventhandler of Pluripotencyの略です。Stupid-Triggered EventArgs of PluripotencyでStep でもいいかなと考えました。いっそのこと、Stimulus-Triggered Actions of PluripotencyでStapってのはどうでしょうか?

要するにEventArgsを型引数クラスで継承して万能 細胞 関数化してるってことなんですよ。

次回は、この応用でランチャにタスクを実装した方式を掲載ます

本文

基底関数群

public class AtepEventArgs<T> : EventArgs
{
        public T Value { get; private set; }
        public AtepEventArgs(T val)
        {
            Value = val;
        }
}
public delegate void EventHandler<TSender, TEventArgs>(TSender sender, TEventArgs e);
public interface ILauncher<T>
{
    event EventHandler<object, AtepEventArgs<T>> Raise;
}
public class AtepLauncher<T> : ILauncher<T>
{
        private T arg = default(T);
        public AtepLauncher()
        {
        }
        public AtepLauncher(T a)
        {
            this.arg = a;
        }
        public T Arg
        {
            get
            {
                return this.arg;
            }
            set
            {
                this.arg = value;
                OnChanged(this, new AtepEventArgs<T>(this.arg));
            }
        }
        // Delegate
        public event EventHandler<object, AtepEventArgs<T>> Raise;
        // Trigger
        public void OnChanged(object sender, AtepEventArgs<T> e)
        {
            if (Raise != null)
            {
                // Call the Event
                Raise(this, e);
            }
        }
}
public class AtepContainer<T>
{ 
        private List<ILauncher<T>> launcher;
        public AtepContainer()
        {
            this.launcher = new List<ILauncher<T>>();
        }

        public void Add(ILauncher<T> lchr)
        {
            lchr.Raise += new EventHandler<object, AtepEventArgs<T>>(HandleChanged);
            this.launcher.Add(lchr);
        }

        internal virtual void HandleChanged(object sender, AtepEventArgs<T> e)
        {
            // イベント発火, ここにoverride メソッドを記述
            Console.WriteLine("Received event. value={0}", e.Value);
        }
}

目的別の関数

/// <summary>
/// (目的の)型
/// </summary>
public class MyItem
{
        public MyItem()
        {
        }
        public MyItem(int n, string s)
        {
            Number = n;
            TextMessage = s;
        }

        public int Number { get; set; }
        public string TextMessage { get; set; }
}

/// <summary>
/// (目的の)メイン
/// </summary>
internal class Test
{
        private static Test _instance { get; set; }
        public static Test GetInstance()
        {
            return _instance;
        }

        private static void Main(string[] args)
        {
            var myLauncher = new AtepLauncher<MyItem>();

            var container = new MyContainer();

            container.Add(myLauncher);

            myLauncher.Arg = new MyItem(1, "Item1");

            // Keep the console window open in debug mode.
            System.Console.WriteLine("Press any key to exit.");
            System.Console.ReadKey();

        }
}

コード全体

using System;
using System.Collections.Generic;
using System.Threading;

/// <summary>
/// Note : 
/// Atep = Arbitary-Triggered Eventhandler of Pluripotency
/// </summary>
namespace RaiseBaseClassEventsTestPart3
{
    public class AtepEventArgs<T> : EventArgs
    {
        public T Value { get; private set; }
        public AtepEventArgs(T val)
        {
            Value = val;
        }
    }
    public delegate void EventHandler<TSender, TEventArgs>(TSender sender, TEventArgs e);
    public interface ILauncher<T>
    {
        event EventHandler<object, AtepEventArgs<T>> Raise;
    }
    public class AtepLauncher<T> : ILauncher<T>
    {
        private T arg = default(T);
        public AtepLauncher()
        {
        }
        public AtepLauncher(T a)
        {
            this.arg = a;
        }
        public T Arg
        {
            get
            {
                return this.arg;
            }
            set
            {
                this.arg = value;
                OnChanged(this, new AtepEventArgs<T>(this.arg));
            }
        }
        // Delegate
        public event EventHandler<object, AtepEventArgs<T>> Raise;
        // Trigger
        public void OnChanged(object sender, AtepEventArgs<T> e)
        {
            if (Raise != null)
            {
                // Call the Event
                Raise(this, e);
            }
        }
    }
    public class AtepContainer<T>
    { 
        private List<ILauncher<T>> launcher;
        public AtepContainer()
        {
            this.launcher = new List<ILauncher<T>>();
        }

        public void Add(ILauncher<T> lchr)
        {
            lchr.Raise += new EventHandler<object, AtepEventArgs<T>>(HandleChanged);
            this.launcher.Add(lchr);
        }

        internal virtual void HandleChanged(object sender, AtepEventArgs<T> e)
        {
            // イベント発火, ここにoverride メソッドを記述
            Console.WriteLine("Received event. value={0}", e.Value);
        }
    }

    /// <summary>
    /// (目的の) ランチャコンテナ
    /// </summary>
    public class MyContainer : AtepContainer<MyItem>
    {
        internal override void HandleChanged(object sender, AtepEventArgs<MyItem> e)
        {
            if (e.Value == null)
                return;
            var item = e.Value as MyItem;
            var s = string.Format("({0}, {1})", item.Number.ToString(), item.TextMessage);
            Console.WriteLine("Received event." + s);
        }

    }

    /// <summary>
    /// (目的の)型
    /// </summary>
    public class MyItem
    {
        public MyItem()
        {
        }
        public MyItem(int n, string s)
        {
            Number = n;
            TextMessage = s;
        }

        public int Number { get; set; }
        public string TextMessage { get; set; }
    }

    /// <summary>
    /// (目的の)メイン
    /// </summary>
    internal class Test
    {
        private static Test _instance { get; set; }
        public static Test GetInstance()
        {
            return _instance;
        }

        private static void Main(string[] args)
        {
            var myLauncher = new AtepLauncher<MyItem>();

            var container = new MyContainer();

            container.Add(myLauncher);

            myLauncher.Arg = new MyItem(1, "Item1");

            // Keep the console window open in debug mode.
            System.Console.WriteLine("Press any key to exit.");
            System.Console.ReadKey();

        }
    }

}

参考