All Articles

C#

C# Event, Event Handler, Delegate(정리하는중)

Event, Event Handler에 대해서 궁금한거 다 구현해서 정리. 글보단 그림으로.

 

1. delegate를 사용한 기본적인 방식들

2. EventArgs를 상속받아 사용하는 방법들

3. Bridge 패턴으로 연결한 방법들

4.(수정중) INotifyPropertyChanged랑 ObservableCollection 같은 Observer와의 이벤트 핸들러에 관해서

 


1. Base event with delegate

using System;

// Using event delegate
class Publisher
{
    public delegate void MyEventHandler();
    public event MyEventHandler MyEvent;
    public void DoEvent()
    {
        MyEvent?.Invoke();
    }
}

class Subscriber
{
    static void Main(string[] args)
    {
        Publisher publisher = new Publisher();

        publisher.MyEvent += new Publisher.MyEventHandler(doAction1);

        Console.WriteLine("Do Event");
        publisher.DoEvent();

        publisher.MyEvent += new Publisher.MyEventHandler(doAction2);

        Console.WriteLine("Do Event");
        publisher.DoEvent();
    }

    static void doAction1()
    {
        Console.WriteLine("MyEvent call doAction1");
    }

    static void doAction2()
    {
        Console.WriteLine("MyEvent call doAction2");
    }
}

 

Do Event
MyEvent call doAction1
Do Event
MyEvent call doAction1
MyEvent call doAction2
Press any key to continue . . .

 

 

doAction1, doAction2는 MyEventHandler라는 delegate로 wrap.

 

1.2. Remove handlers with delegate

1.2.1. Remove doAction1

Publisher publisher = new Publisher();

publisher.MyEvent += new Publisher.MyEventHandler(doAction1);

Console.WriteLine("Do Event");
publisher.DoEvent();

publisher.MyEvent += new Publisher.MyEventHandler(doAction2);

Console.WriteLine("Do Event");
publisher.DoEvent();

// Added this lines from 1.
publisher.MyEvent -= new Publisher.MyEventHandler(doAction1);

Console.WriteLine("Do Event");
publisher.DoEvent();
// Added this lines from 1.

 

Do Event
MyEvent call doAction1
Do Event
MyEvent call doAction1
MyEvent call doAction2
Do Event
MyEvent call doAction2
Press any key to continue . . .

 

1.2.2. Remove doAction2

Publisher publisher = new Publisher();

publisher.MyEvent += new Publisher.MyEventHandler(doAction1);

Console.WriteLine("Do Event");
publisher.DoEvent();

publisher.MyEvent += new Publisher.MyEventHandler(doAction2);

Console.WriteLine("Do Event");
publisher.DoEvent();

// Added this lines from 1.
publisher.MyEvent -= new Publisher.MyEventHandler(doAction2);

Console.WriteLine("Do Event");
publisher.DoEvent();
// Added this lines from 1.

 

Do Event
MyEvent call doAction1
Do Event
MyEvent call doAction1
MyEvent call doAction2
Do Event
MyEvent call doAction1
Press any key to continue . . .

 

1.3. Remove handler that wasn't added

using System;

// Using event delegate
class Publisher
{
    public delegate void MyEventHandler();
    public event MyEventHandler MyEvent;
    public void DoEvent()
    {
        MyEvent?.Invoke();
    }
}

class Subscriber
{
    static void Main(string[] args)
    {
        Publisher publisher = new Publisher();

        publisher.MyEvent += new Publisher.MyEventHandler(doAction1);

        Console.WriteLine("Do Event");
        publisher.DoEvent();

        publisher.MyEvent += new Publisher.MyEventHandler(doAction2);

        Console.WriteLine("Do Event");
        publisher.DoEvent();

        // Added this lines from 1.
        publisher.MyEvent -= new Publisher.MyEventHandler(doAction3);

        Console.WriteLine("Do Event");
        publisher.DoEvent();
        // End of Added this lines from 1.
    }

    static void doAction1()
    {
        Console.WriteLine("MyEvent call doAction1");
    }

    static void doAction2()
    {
        Console.WriteLine("MyEvent call doAction2");
    }

    // Added this lines from 1.
    static void doAction3()
    {
        Console.WriteLine("MyEvent call doAction3");
    }
    // End of Added this lines from 1.
}

 

Do Event
MyEvent call doAction1
Do Event
MyEvent call doAction1
MyEvent call doAction2
Do Event
MyEvent call doAction1
MyEvent call doAction2
Press any key to continue . . .

 

1.4. Add a action serveral times and remove it

using System;

// Using event delegate
class Publisher
{
    public delegate void MyEventHandler();
    public event MyEventHandler MyEvent;
    public void DoEvent()
    {
        MyEvent?.Invoke();
    }
}

class Subscriber
{
    static void Main(string[] args)
    {
        Publisher publisher = new Publisher();

        publisher.MyEvent += new Publisher.MyEventHandler(doAction1);

        Console.WriteLine("Do Event");
        publisher.DoEvent();

        publisher.MyEvent += new Publisher.MyEventHandler(doAction1);

        Console.WriteLine("Do Event");
        publisher.DoEvent();

        publisher.MyEvent -= new Publisher.MyEventHandler(doAction1);

        Console.WriteLine("Do Event");
        publisher.DoEvent();
    }

    static void doAction1()
    {
        Console.WriteLine("MyEvent call doAction1");
    }
}

 

Do Event
MyEvent call doAction1
Do Event
MyEvent call doAction1
MyEvent call doAction1
Do Event
MyEvent call doAction1
Press any key to continue . . .

 

 


2. C# System.EventHandler instead of custom delegate

C# 시스템이 제공하는 public delegate void EventHandler(Object sender, EventArgs e)를 사용.

 

 

using System;

class Publisher
{
    public event EventHandler MyEvent;
    public void DoEvent()
    {
        MyEvent?.Invoke(this, new EventArgs());
    }
}

class Subscriber
{
    static void Main(string[] args)
    {
        Publisher publisher = new Publisher();

        publisher.MyEvent += new EventHandler(doAction1);

        Console.WriteLine("Do Event");
        publisher.DoEvent();

        publisher.MyEvent += new EventHandler(doAction2);

        Console.WriteLine("Do Event");
        publisher.DoEvent();
    }

    static void doAction1(object sender, EventArgs e)
    {
        Console.WriteLine("MyEvent call doAction1");
    }

    static void doAction2(object sender, EventArgs e)
    {
        Console.WriteLine("MyEvent call doAction2");
    }
}

 

Do Event
MyEvent call doAction1
Do Event
MyEvent call doAction1
MyEvent call doAction2
Press any key to continue . . .

 

2.1. C# EventArgs with delegate

using System;

class PublisherEventArgs : EventArgs
{
    private string _Message;

    public string Message { get => _Message; set => _Message = value; }
}

class Publisher
{
    public delegate void MyEventHandler(object sender, PublisherEventArgs e);
    public event MyEventHandler MyEvent;
    public void DoEvent()
    {
        PublisherEventArgs eventData = new PublisherEventArgs();
        eventData.Message = "This is message";
        MyEvent?.Invoke(this, eventData);
    }
}

class Subscriber
{
    static void Main(string[] args)
    {
        Publisher publisher = new Publisher();

        publisher.MyEvent += new Publisher.MyEventHandler(doAction);

        Console.WriteLine("Do Event");
        publisher.DoEvent();
    }

    static void doAction(object sender, PublisherEventArgs e)
    {
        Console.WriteLine("MyEvent call doAction");
        Console.WriteLine("Message: {0}", e.Message);
    }
}

 

Do Event
MyEvent call doAction
Message: This is message
Press any key to continue . . .

 

2.2. C# EventArgs custom

아직은 경험이 적어 주로 어떤 방식을 사용하는지는 정확히 모르나 이 방식을 사용하기로함. 손수 바꾸기도 쉬움. 정확히 알았을때 수정 필요

 

 

using System;

public class PublisherEventArgs : EventArgs
{
    private string _Message;

    public string Message { get => _Message; set => _Message = value; }
}

public class Publisher
{
    public event EventHandler<PublisherEventArgs> MyEvent;
    public void DoEvent(object sender, EventArgs eventData)
    {
        MyEvent?.Invoke(this, eventData as PublisherEventArgs);
    }
}

public class Subscriber
{
    public void doAction(object sender, PublisherEventArgs e)
    {
        Console.WriteLine("MyEvent call doAction");
        Console.WriteLine("Message: {0}", e.Message);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Publisher publisher = new Publisher();
        Subscriber subscriber = new Subscriber();

        publisher.MyEvent += subscriber.doAction;

        PublisherEventArgs eventData = new PublisherEventArgs
        {
            Message = "This is message"
        };
        Console.WriteLine("Do Event");
        publisher.DoEvent(subscriber, eventData);
    }
}

 

Do Event
MyEvent call doAction
Message: This is message
Press any key to continue . . .

 

 

 


3. EventHandler with Bridge Pattern 개요

인터페이스랑 모듈로 모듈화하기 전에 위의 기본 패턴을 객체화해봄

 

using System;

public class PublisherEventArgs : EventArgs
{
    private string _Message;

    public string Message { get => _Message; set => _Message = value; }
}

public class Publisher
{
    public event EventHandler<PublisherEventArgs> MyEvent;
    public void DoEvent(object sender, EventArgs eventData)
    {
        MyEvent?.Invoke(this, eventData as PublisherEventArgs);
    }
}

public class Subscriber
{
    private Publisher mPublisher;
    private PublisherEventArgs mEventData;

    public Subscriber(Publisher publisher)
    {
        mPublisher = publisher;
        mPublisher.MyEvent += Event_doAction;

        mEventData = new PublisherEventArgs();
        mEventData.Message = "This is message";
    }

    public void DoAction(string message)
    {
        mEventData.Message = message;

        Console.WriteLine("Do Event");
        mPublisher.DoEvent(this, mEventData);
    }

    private void Event_doAction(object sender, PublisherEventArgs e)
    {
        Console.WriteLine("MyEvent call doAction");
        Console.WriteLine("Message: {0}", e.Message);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Publisher publisher = new Publisher();
        Subscriber subscriber = new Subscriber(publisher);

        subscriber.DoAction("Do Action");
    }
}

 

Do Event
MyEvent call doAction
Message: Do Action
Press any key to continue . . .

 

3.1. EventHandler with Bridge Pattern 모듈화

Publisher -> Interface, Subscriber -> Module

 

using System;

public class CustomEventArgs : EventArgs
{
    private string _Message;

    public string Message { get => _Message; set => _Message = value; }
}

public class Module
{
    private Interface mInterface;
    private CustomEventArgs mEventData;

    public Module(Interface _interface)
    {
        mInterface = _interface;
        mEventData = new CustomEventArgs();
    }

    public void WriteMessage(string _message)
    {
        mEventData.Message = _message;

        Console.WriteLine("Do Event");
        mInterface.raiseEvent(this, mEventData);
    }
}

public class Interface
{
    protected Module mModule;

    protected void InitializeInterface()
    {
        mModule = new Module(this);
    }

    public void WriteMessage(string _message)
    {
        mModule.WriteMessage(_message);
    }

    public event EventHandler<CustomEventArgs> OnReceivedEvent;
    public void raiseEvent(object sender, EventArgs eventData)
    {
        OnReceivedEvent?.Invoke(this, eventData as CustomEventArgs);
    }
}


class Implement : Interface
{
    public Implement()
    {
        InitializeInterface();

        OnReceivedEvent += Event_writeMessage;
    }

    private void Event_writeMessage(object sender, CustomEventArgs e)
    {
        Console.WriteLine("MyEvent call doAction");
        Console.WriteLine("Message: {0}", e.Message);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Implement implement = new Implement();

        implement.WriteMessage("This is message");
    }
}

 

Do Event
MyEvent call doAction
Message: This is message
Press any key to continue . . .

 

 

 

3.2. WPF app with event handler, event

3.3. 멀티쓰레드 기본

3.4. 멀티쓰레드 양방향

3.3. 멀티쓰레드 기본

3.4. 멀티쓰레드 양방향