2015-07-23 6 views
2

Я пытаюсь отменить подписку на мой метод. У меня есть этот код:Отказаться от подписки на оригинальное событие, когда попробуйте отказаться от подписки на переменную этого EventHandler

public event EventHandler MenuItemSelectionChanged; 

var eh = MenuItemSelectionChanged; 
eh -= TheMethod; 

После запуска выше код результата:

MenuItemSelectionChanged: Is Not Null

эш: Is Null

Но я хочу отказаться от подписки TheMethod от MenuItemSelectionChanged, используя eh (указатель на EventHandler). Как я могу использовать eh удалить TheMethod из eh и MenuItemSelectionChanged

мне нужен этот результат:

MenuItemSelectionChanged: Is Null

эль: Is Null

Мой главный сценарий:

Внутри TargetClass.cs:

public event EventHandler MenuItemSelectionChanged; 

    public void UnsubscribeFromEvent(ThisClassEventHandlerNames eventHandlerName, Dictionary<FrameworkElement, MethodInfo> eventHandlerInfos) 
    { 
     var eh = GetEventHandler(eventHandlerName); 
     if (eh == null) return; 

     foreach (var eventHandlerInfo in eventHandlerInfos) 
     { 
      var info = eventHandlerInfo; 

      if (eh == null) 
       break; 

       var invocationList = eh.GetInvocationList().Where(x => 
        Equals(x.Target, info.Key) && 
        x.Method == info.Value); 

      foreach (var myDeligate in invocationList) 
      { 
       if (eh == null) 
        break; 

       // I HAVE A PROBLEM HERE>> 
       eh -= (EventHandler) myDeligate; 
       // RESULT: eh is null BUT MenuItemSelectionChanged is not null 
      } 
     } 
    } 

    public enum ThisClassEventHandlerNames 
    { 
     MenuItemSelectionChanged 
    } 

    private EventHandler GetEventHandler(ThisClassEventHandlerNames eventHandlerName) 
    { 
     EventHandler result = null; 
     switch (eventHandlerName) 
     { 
      case ThisClassEventHandlerNames.MenuItemSelectionChanged: 
      { 
       result = MenuItemSelectionChanged; 
       break; 
      } 
      default: 
      { 
       result = null; 
       break; 
      } 
     } 
     return result; 
    } 

Я называю приведенный выше код в моем WPF пользовательских элементов управления с некоторыми кодами, как это:

Внутри MyUserControl.cs:

TargetClassObject.UnsubscribeFromEvent(
    TargetClass.ThisClassEventHandlerNames.MenuItemSelectionChanged, 
    new Dictionary<FrameworkElement, MethodInfo> 
    { 
     { 
      this, 
      Infrastructure.Utility.GetMethodInfo<MyUserControl>(x => x.MenuControl_MenuItemSelectionChanged(null, null)) 
     } 
    }); 

Действительно я хочу отказаться от подписки метод из события путем вызова, метод внутри этого класса (targetClass) по этим параметрам:

A) Значение перечисления (чтобы получить событие от него)

B) инфо метод (отписать свой метод от случая)

Примечание: Моя платформа C#, WPF, .NET Framework 4.5

ответ

1

Когда вы перемещаете MenuItemSelectionChanged в переменную, а затем присваиваете этой переменной, вы фактически не изменяете список вызовов исходного делегата. eh -= TheMethod; - это то же самое, что и eh = eh - TheMethod; (если вы находитесь внутри класса), но это производит новый MulticastDelegate и не изменяет оригинал.

Так, чтобы ответить на ваш первый код:

public event EventHandler MenuItemSelectionChanged; 

var eh = MenuItemSelectionChanged; 
eh -= TheMethod; 
MenuItemSelectionChanged = eh; 

Однако, вы хотите, чтобы динамически изменять событие, так как вы можете добавить второй метод, который получает ThisClassEventHandlerNames и EventHandler и назначает его обратно.Или вы можете изменить метод GetEventHandler вернуть ссылки обработчика:

private delegate void HandlerModifier(ref EventHandler handler); 
private bool ModifyEventHandler(ThisClassEventHandlerNames eventHandlerName, HandlerModifier mod) 
{ 
    switch (eventHandlerName) 
    { 
     case ThisClassEventHandlerNames.MenuItemSelectionChanged: 
     { 
      mod(ref MenuItemSelectionChanged); 
      return true; 
     } 
     default: 
     { 
      return false; 
     } 
    } 
} 

public void UnsubscribeFromEvent(ThisClassEventHandlerNames eventHandlerName, Dictionary<FrameworkElement, MethodInfo> eventHandlerInfos) 
{ 
    ModifyEventHandler(
     eventHandlerName, 
     delegate(ref EventHandler eh) 
     { 
      if (eh == null) return; 

      foreach (var eventHandlerInfo in eventHandlerInfos) 
      { 
       var info = eventHandlerInfo; 

       if (eh == null) 
        break; 

        var invocationList = eh.GetInvocationList().Where(x => 
         Equals(x.Target, info.Key) && 
         x.Method == info.Value); 

       foreach (var myDeligate in invocationList) 
       { 
        if (eh == null) 
         break; 

        // I HAVE A PROBLEM HERE>> 
        eh -= (EventHandler) myDeligate; 
        // RESULT: eh is null BUT MenuItemSelectionChanged is not null 
       } 
      } 
     } 
    ); 
} 

ModifyEventHandler сейчас «возвращают» ссылку на обработчик, поэтому все изменения к нему передается в MenuItemSelectionChanged.

Смежные вопросы