C# - 从浏览器中删除事件
本文关键字:删除 事件 浏览器 | 更新日期: 2023-09-27 18:32:19
我添加一个事件webBrowser
如下代码:
webBrowser.DocumentCompleted += (s, e) => {};
现在如何删除其中的此事件?像这样沉吟:
webBrowser.DocumentCompleted += (s, e) => {
webBrowser.DocumentCompleted -= this;
};
您只需要对委托的引用。像这样:
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
事件触发之前分离。