[C#] 이벤트에서 모든 이벤트 핸들러를 제거하는 방법

컨트롤에서 새 이벤트 처리기를 만들려면 다음을 수행하십시오.

c.Click += new EventHandler(mainFormButton_Click);

아니면 이거

c.Click += mainFormButton_Click;

이벤트 핸들러를 제거하려면 다음을 수행하십시오.

c.Click -= mainFormButton_Click;

그러나 이벤트에서 모든 이벤트 핸들러를 어떻게 제거합니까?



답변

MSDN 포럼 에서 해결책을 찾았습니다 . 아래 샘플 코드는에서 모든 Click이벤트를 제거합니다 button1.

public partial class Form1 : Form
{
        public Form1()
        {
            InitializeComponent();

            button1.Click += button1_Click;
            button1.Click += button1_Click2;
            button2.Click += button2_Click;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Hello");
        }

        private void button1_Click2(object sender, EventArgs e)
        {
            MessageBox.Show("World");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            RemoveClickEvent(button1);
        }

        private void RemoveClickEvent(Button b)
        {
            FieldInfo f1 = typeof(Control).GetField("EventClick",
                BindingFlags.Static | BindingFlags.NonPublic);
            object obj = f1.GetValue(b);
            PropertyInfo pi = b.GetType().GetProperty("Events",
                BindingFlags.NonPublic | BindingFlags.Instance);
            EventHandlerList list = (EventHandlerList)pi.GetValue(b, null);
            list.RemoveHandler(obj, list[obj]);
        }
    }
}


답변

너희들은이 길을 너무 힘들게 만들고있다. 이 쉬운 일이다 :

void OnFormClosing(object sender, FormClosingEventArgs e)
{
    foreach(Delegate d in FindClicked.GetInvocationList())
    {
        FindClicked -= (FindClickedHandler)d;
    }
}


답변

모든 이벤트 핸들러 제거 에서 :

이벤트를 단순히 널로 설정할 수 없기 때문에 직접 아니오.

간접적으로 실제 이벤트를 비공개로 만들고 주변에 추가 / 삭제되는 모든 대리자를 추적하는 속성을 만들 수 있습니다.

다음을 수행하십시오.

List<EventHandler> delegates = new List<EventHandler>();

private event EventHandler MyRealEvent;

public event EventHandler MyEvent
{
    add
    {
        MyRealEvent += value;
        delegates.Add(value);
    }

    remove
    {
        MyRealEvent -= value;
        delegates.Remove(value);
    }
}

public void RemoveAllEvents()
{
    foreach(EventHandler eh in delegates)
    {
        MyRealEvent -= eh;
    }
    delegates.Clear();
}

답변

허용 된 답변이 가득 찼습니다. {add;로 선언 된 이벤트에는 작동하지 않습니다. 없애다;}

작동 코드는 다음과 같습니다.

public static void ClearEventInvocations(this object obj, string eventName)
{
    var fi = obj.GetType().GetEventField(eventName);
    if (fi == null) return;
    fi.SetValue(obj, null);
}

private static FieldInfo GetEventField(this Type type, string eventName)
{
    FieldInfo field = null;
    while (type != null)
    {
        /* Find events defined as field */
        field = type.GetField(eventName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic);
        if (field != null && (field.FieldType == typeof(MulticastDelegate) || field.FieldType.IsSubclassOf(typeof(MulticastDelegate))))
            break;

        /* Find events defined as property { add; remove; } */
        field = type.GetField("EVENT_" + eventName.ToUpper(), BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic);
        if (field != null)
            break;
        type = type.BaseType;
    }
    return field;
}


답변

존재하지 않는 이벤트 핸들러를 삭제해도 아무런 해가 없습니다. 따라서 어떤 핸들러가 있는지 아는 경우 간단히 모든 핸들러를 삭제할 수 있습니다. 방금 비슷한 경우가있었습니다. 경우에 따라 도움이 될 수 있습니다.

처럼:

// Add handlers...
if (something)
{
    c.Click += DoesSomething;
}
else
{
    c.Click += DoesSomethingElse;
}

// Remove handlers...
c.Click -= DoesSomething;
c.Click -= DoesSomethingElse;


답변

실제로이 방법을 사용하고 있으며 완벽하게 작동합니다. I이었다 Aeonhack에 의해 작성된 코드에 의해 ‘영감’ 여기 .

Public Event MyEvent()
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    If MyEventEvent IsNot Nothing Then
        For Each d In MyEventEvent.GetInvocationList ' If this throws an exception, try using .ToArray
            RemoveHandler MyEvent, d
        Next
    End If
End Sub

MyEventEvent 필드는 숨겨져 있지만 존재합니다.

디버깅 d.target하면 객체가 실제로 이벤트를 처리하는 방법을 볼 수 있습니다.d.method 방법 그 방법을 볼 수 있습니다. 당신은 그것을 제거해야합니다.

잘 작동합니다. 이벤트 핸들러로 인해 더 이상 GC되지 않는 오브젝트가 없습니다.


답변

나는 여기에 표시된 모든 완벽한 솔루션을 싫어했고, 지금 혼합하고 테스트했으며 모든 이벤트 핸들러에서 일했습니다.

public class MyMain()
    public void MyMethod() {
        AnotherClass.TheEventHandler += DoSomeThing;
    }

    private void DoSomething(object sender, EventArgs e) {
        Debug.WriteLine("I did something");
        AnotherClass.ClearAllDelegatesOfTheEventHandler();
    }

}

public static class AnotherClass {

    public static event EventHandler TheEventHandler;

    public static void ClearAllDelegatesOfTheEventHandler() {

        foreach (Delegate d in TheEventHandler.GetInvocationList())
        {
            TheEventHandler -= (EventHandler)d;
        }
    }
}

쉬운! Stephen Punak에게 감사합니다.

나는 일반적인 로컬 메소드를 사용하여 델리게이트를 제거하고 다른 델리게이트가 설정 될 때 로컬 메소드가 다른 경우에 호출 되었기 때문에 그것을 사용했습니다.