“使用”以在我完成后断开与事件的连接

本文关键字:断开 事件 连接 使用 | 更新日期: 2023-09-27 18:37:15

我目前有这样的代码,一个async的方法:

MyEventHandler handler = (sender, e) => ...
Foo.My += handler;
await Foo.Bar();  // Fires event `My` 
Foo.My -= handler;

我想使用 using 语句来处理此代码的前后性质。也许像这样:

using (ListenUntilDispose(Foo.My, handler))
{
    await Foo.Bar();
}

但是我想不出写ListenTemporarily.

有没有办法做到这一点?

“使用”以在我完成后断开与事件的连接

是的,有,但不幸的是,通常执行此操作并不简单,因为事件在 C# 中没有具体化 - 我的意思是,你不能传递对事件的引用。

在反应式扩展中,这是通过使用反射来解决的,因此您可以通过传递定义事件的对象以及事件名称作为字符串将事件传递给函数:

using(ListenUntilDispose(Foo, "My", handler))
{
    await Foo.Bar();
}

但是,我的 reflection-fu 不是很强,而且您也失去了静态类型安全性,这意味着编译器无法检查handler是否真的与Foo.My匹配。这是另一个不那么舒服但也可能适合你的建议,如果你的目标真的是"我想使用using",而不一定是"我想要最容易阅读的解决方案":

class DelegateDisposable : IDisposable
{
    private readonly Action m_dispose;
    public DelegateDisposable(Action onDispose)
    {
        m_dispose = onDispose;
    }
    public void Dispose()
    {
        m_dispose();
    }
}

用法将是:

Foo.My += handler;
using(new DelegateDisposable(() => Foo.My -= handler))
{
    await Foo.Bar();
}

免责声明:写在编辑框中,所以未经测试:)