尝试取消订阅该EventHandler

时间:2015-07-23 20:05:44

标签: c#

我试图取消订阅我的活动的附加方法。我有这段代码:

public event EventHandler MenuItemSelectionChanged;

var eh = MenuItemSelectionChanged;
eh -= TheMethod;

运行后上面的代码结果是:

  

MenuItemSelectionChanged:不为空

     

el:Null

但我希望使用TheMethod(指向EventHandler的指针)取消订阅MenuItemSelectionChanged eh。如何使用ehTheMethodeh移除MenuItemSelectionChanged

我需要这个结果:

  

MenuItemSelectionChanged:Null

     

el: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 个答案:

答案 0 :(得分:1)

当您将MenuItemSelectionChanged移动到变量然后分配给该变量时,您并没有真正更改原始委托的调用列表。 eh -= TheMethod;eh = eh - TheMethod;相同(如果您在课堂内),但这会产生新的MulticastDelegate,并且不会修改原始版本。

所以回答你的第一个代码:

public event EventHandler MenuItemSelectionChanged;

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

但是,您希望动态更改事件,因此您可以添加第二个获取ThisClassEventHandlerNamesEventHandler的方法并将其分配回来。或者您可以修改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现在&#34;返回&#34;对处理程序的引用,因此对它的所有更改都将传递给MenuItemSelectionChanged