C# - 从浏览器中删除事件

本文关键字:删除 事件 浏览器 | 更新日期: 2023-09-27 18:32:19

我添加一个事件webBrowser如下代码:

webBrowser.DocumentCompleted += (s, e) => {};

现在如何删除其中的此事件?像这样沉吟:

webBrowser.DocumentCompleted += (s, e) => {
webBrowser.DocumentCompleted -= this;
};

C# - 从浏览器中删除事件

您只需要对委托的引用。像这样:

WebBrowserDocumentCompletedEventHandler complete = null;
complete = (s, e) => {
    webBrowser.DocumentComplete -= complete;
};
webBrowser.DocumentComplete += complete;

我把这个答案作为接受答案的辅助

可以执行一些委托魔术,以避免显式获取用于分离处理程序的引用。

以下是可以编写的最终代码(在您的webBrowser情况下):

IDisposable subscription =
    Disposable
        .HandleOnce(
            h => webBrowser.DocumentCompleted += h,
            h => webBrowser.DocumentCompleted -= h,
            (s, e) =>
            {
                Console.WriteLine("DocumentCompleted!");
            });

保留对subscription的引用是可选的,但调用 subscription.Dispose() 允许处理程序在运行一次之前被取消。

首先,您需要以下代码:

public static class Disposable
{
    public static IDisposable Create(Action dispose)
    {
        if (dispose == null)
            throw new ArgumentNullException("dispose");
        return (IDisposable)new AnonymousDisposable(dispose);
    }
    private sealed class AnonymousDisposable : IDisposable
    {
        private volatile Action _dispose;
        public AnonymousDisposable(Action dispose)
        {
            _dispose = dispose;
        }
        public void Dispose()
        {
            Action action = Interlocked.Exchange<Action>(ref _dispose, (Action)null);
            if (action != null)
            {
                action();
            }
        }
    }
}

这允许将任何操作转换为IDisposable,该将在调用.Dispose()时调用该操作一次。

所以,这段代码:

var subscription = Disposable.Create(() => Console.WriteLine("Done."));
subscription.Dispose();
subscription.Dispose();

。导致Done.仅在主机上打印一次。

现在,可以将 HandleOnce 方法添加到 Disposable 类中:

public static IDisposable HandleOnce(
    Action<WebBrowserDocumentCompletedEventHandler> addHandler,
    Action<WebBrowserDocumentCompletedEventHandler> removeHandler,
    WebBrowserDocumentCompletedEventHandler handler)
{
    if (addHandler == null)
        throw new ArgumentNullException("addHandler");
    if (removeHandler == null)
        throw new ArgumentNullException("removeHandler");
    if (handler == null)
        throw new ArgumentNullException("handler");
    WebBrowserDocumentCompletedEventHandler nested = null;
    nested = (s, e) =>
    {
        removeHandler(nested);
        handler(s, e);
    };
    addHandler(nested);
    return Disposable.Create(() => removeHandler(nested));
}

现在,可以制作此代码的完全通用版本,不必编码即可了解像WebBrowserDocumentCompletedEventHandler这样的委托。在这里:

public static class Disposable
{
    public static IDisposable Create(Action dispose)
    {
        if (dispose == null)
            throw new ArgumentNullException("dispose");
        return (IDisposable)new AnonymousDisposable(dispose);
    }
    public static IDisposable Handle<TDelegate, TEventArgs>(
        Action<TDelegate> addHandler,
        Action<TDelegate> removeHandler,
        TDelegate handler)
    {
        if (addHandler == null)
            throw new ArgumentNullException("addHandler");
        if (removeHandler == null)
            throw new ArgumentNullException("removeHandler");
        if (handler == null)
            throw new ArgumentNullException("handler");
        addHandler(handler);
        return Disposable.Create(() => removeHandler(handler));
    }
    public static IDisposable HandleOnce<TDelegate, TEventArgs>(
        Action<TDelegate> addHandler,
        Action<TDelegate> removeHandler,
        TDelegate handler)
    {
        if (addHandler == null)
            throw new ArgumentNullException("addHandler");
        if (removeHandler == null)
            throw new ArgumentNullException("removeHandler");
        if (handler == null)
            throw new ArgumentNullException("handler");
        Action<object, TEventArgs> inner =
            CreateDelegate<Action<object, TEventArgs>>(
                handler,
                typeof(TDelegate).GetMethod("Invoke"));
        TDelegate outer = default(TDelegate);
        IDisposable detach = Disposable.Create(() => removeHandler(outer));
        Action<object, TEventArgs> nested = (s, e) =>
        {
            removeHandler(outer);
            inner(s, e);
        };
        outer = CreateDelegate<TDelegate>(
            nested,
            typeof(Action<object, TEventArgs>).GetMethod("Invoke"));
        addHandler(outer);
        return detach;
    }
    public static TDelegate CreateDelegate<TDelegate>(object o, MethodInfo method)
    {
        return (TDelegate)(object)Delegate.CreateDelegate(typeof(TDelegate), o, method);
    }
    public static IDisposable Handle(
        Action<EventHandler> addHandler,
        Action<EventHandler> removeHandler,
        EventHandler handler)
    {
        return Disposable.Handle<EventHandler, EventArgs>(addHandler, removeHandler, handler);
    }
    public static IDisposable HandleOnce(
        Action<EventHandler> addHandler,
        Action<EventHandler> removeHandler,
        EventHandler handler)
    {
        if (addHandler == null)
            throw new ArgumentNullException("addHandler");
        if (removeHandler == null)
            throw new ArgumentNullException("removeHandler");
        if (handler == null)
            throw new ArgumentNullException("handler");
        EventHandler nested = null;
        IDisposable detach = Disposable.Create(() => removeHandler(nested));
        nested = (s, e) =>
        {
            detach.Dispose();
            handler(s, e);
        };
        addHandler(nested);
        return detach;
    }
    private sealed class AnonymousDisposable : IDisposable
    {
        private volatile Action _dispose;
        public AnonymousDisposable(Action dispose)
        {
            _dispose = dispose;
        }
        public void Dispose()
        {
            Action action = Interlocked.Exchange<Action>(ref _dispose, (Action)null);
            if (action != null)
            {
                action();
            }
        }
    }
}

上面的类还包含用于处理多个事件发生的代码,而不仅仅是 HandleOnce

现在调用它的代码如下所示:

IDisposable subscription =
    Disposable
        .HandleOnce<
                WebBrowserDocumentCompletedEventHandler,
                WebBrowserDocumentCompletedEventArgs>(
            h => webBrowser.DocumentCompleted += h,
            h => webBrowser.DocumentCompleted -= h,
            (s, e) =>
            {
                Console.WriteLine("DocumentCompleted!");
            });

同样,无需保留对subscription的引用,除非您要在DocumentCompleted事件触发之前分离。