是否可以在 lambda 表达式中定位 EventHandler?

2024-01-19

举一个简单的例子,如果我有某种按钮 UI 类,我可以编写一个函数来接受指向其的表达式吗?Click事件处理程序:

SomeMethod<SomeButtonClass>(button => button.Click);

我正在尝试消除当前用于系统的一些魔法字符串,以使事件可等待。有问题的代码源自弗兰克·克鲁格的博客文章 http://praeclarum.org/post/45231096776/await-in-the-land-of-ios-drag-n-drop#alittletrickfunction(如果您想要一些背景知识,值得一读)。

public static Task<TEventArgs> GetEventAsync<TEventArgs>(this object eventSource, string eventName) where TEventArgs : EventArgs {
    //...
    Type type = eventSource.GetType();
    EventInfo ev = type.GetEvent(eventName);
    //...
}

虽然里面的细节可能并不重要,但完整的方法允许您使用Event触发作为完成源Task,使其更易于管理await。对于某些引发事件的类,您可以绑定到Task基于该事件,通过简单的调用。

Task<EventArgs> eventTask = someEventCausingObject.GetEventAsync<EventArgs>("SomeEventHandler");
// traditionally used as someEventCausingObject.SomeEventHandler += ...;
await eventTask;
// Proceed back here when SomeEventHandler event is raised.

我一直在几个项目中愉快地使用它,但它有它的缺点,最大的缺点之一是使用硬编码的事件名称strings。这使得事件名称更改变成运行时异常,并且很难确定事件的使用情况。

我开始尝试制作一个版本,允许EventHandler作为一部分传递Expression目标是这样的:

await someEventCausingObject.GetEventAsync<EventCausingClass, EventArgs>(x => x.SomeEventHandler);

...具有相应的方法签名...

public static Task<TEventArgs> GetEventAsync<TSource, TEventArgs>(this TSource eventSource, Expression<Func<TSource, EventHandler>> eventHandlerExpression) where TEventArgs : EventArgs {
    //...
}

不幸的是,调用代码中的 lambda 表达式会导致编译错误:

Error CS0070: The event `SomeEventHandler' can only appear on the left hand side of += or -= when used outside of the type `EventCausingClass'.

考虑到事件处理程序的通常使用方式,这是有一定道理的,但我希望找到一个比预先指定的字符串名称更好的解决方案。似乎对“表达式”和“事件处理程序”组合的搜索都倾向于被描述 lambda 表达式开头的人所污染。+=事件处理程序分配。我希望我在这里遗漏了一些明显的东西。


不,不可能定位事件。基本上,event 不是真正的类型成员,而只是生成 add_EventName 和 remove_EventName 方法对的 C# 语法。

您可以尝试引用这些内部方法名称,但这在 C# 中是不可能的 -http://msdn.microsoft.com/en-us/library/z47a7kdw.aspx http://msdn.microsoft.com/en-us/library/z47a7kdw.aspx

《SO》中有很多类似的问题,但同样的答案都是“否”——就像 Jon Skeet 的这个问题一样https://stackoverflow.com/a/4756021/2170171 https://stackoverflow.com/a/4756021/2170171

如果你真的很疯狂,你可以尝试类似的事情

private static void Subscribe(Action addHandler)
{
    var IL = addHandler.Method.GetMethodBody().GetILAsByteArray();

    // Magic here, in which we understand ClassName and EventName
    ???
}

用法如

Subscribe(() => new Button().Click += null);

你可以尝试使用塞西尔http://www.mono-project.com/Cecil http://www.mono-project.com/Cecil用于分析 IL,或实现您自己的逻辑,因为对于可预测的代码行来说它应该不会太难。

不过,我认为这不是一个好的解决方案,因为它只是用另一个令人头痛的问题(正确的事件命名)代替了另一个令人头痛的问题(正确的事件命名)。Subscribe呼叫)。不过,它将有助于重命名内容。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以在 lambda 表达式中定位 EventHandler? 的相关文章

随机推荐

  • Halide 与 C 布局 numpy 数组

    我开始使用 Halide 并在 Python 环境中使用它 在该 Python 环境中 数据作为 Numpy 数组传递 它实际上是其他地方定义的 C 数组的别名 但是 当我使用调用 Halide 函数时 出现错误 Constraint vi
  • 使用 python 运行时,Flask 调试模式给出“OSError: [Errno 8] Exec format error”

    所以 这是我制作的一个文件 flaskblog py from flask import Flask app Flask name app route def hello return h1 Home Page h1 这是我第一次运行它的方
  • 仿真给出了正常 for 循环与并行 For 的不同结果

    当我尝试使用普通 for 循环 这是正确的结果 与 Parallel For 时 我对一个简单模拟示例的不同结果感到有点惊讶 请帮我找出可能是什么原因 我观察到 与正常情况相比 并行执行速度非常快 using System using Sy
  • C语言中总线:错误10是什么意思

    下面是我的代码 import
  • div 上的 CSS 不透明度随着时间延迟而不是用户交互而变化

    我正在尝试在 div 中设置一个图像 该图像将在 5 秒内缓慢出现 不透明度从 0 到 1 我有这个代码 fadeDivIn opacity 1 transition opacity 5s ease in moz transition op
  • 我应该预先分配一个 numpy 数组吗?

    我有一个类及其方法 该方法在执行过程中会重复多次 该方法使用一个numpy数组作为临时缓冲区 我不需要在方法调用之间将值存储在缓冲区内 我是否应该创建数组的成员实例以避免方法执行期间内存分配的时间泄漏 我知道最好使用局部变量 但是 Pyth
  • Webgl:写入 gl_FragDepth 的替代方法

    在WebGL中 是否可以写入片段的深度值或以其他方式控制片段的深度值 据我所知 gl FragDepth 不存在于 webgl 1 x 中 但我想知道是否有其他方法 扩展 浏览器特定支持等 来做到这一点 我想要归档的是让光线追踪对象与使用通
  • 如何从 sql server 2012 中删除拥有架构的用户

    我在 Sql Server 2012 中创建了一个新用户 并且 意外地 将他们标记为多个架构的所有者 我本想将它们标记为架构的成员 但我在错误的选项卡上 因为他们现在是架构的所有者 所以我无法取消选择所有权 也无法删除用户 我怎样才能挽回我
  • 如何在 mapstruct 中使用来自不同类的另一个映射

    我想将模型对象映射到 dto 模型 我已经拥有其中一个对象的映射器 如何在另一个类中的另一个映射器中重用此映射器 我有以下模型 Getter AllArgsConstructor ToString public class History
  • 使用更改源时,有没有办法获取 PouchDB 中文档的所有修订?

    我现在正在摆弄 PouchDB 我使用它作为本地存储数据的一种方式 而不将其链接到 CouchDB 我一直在尝试做的是为单个文档创建一个恢复 撤消方法 为此 我想使用 doc 的先前修订版 我在阅读 PouchDB 文档时遇到了更改提要 起
  • 将鼠标悬停在信息框上会在其后面的标记上触发悬停事件

    我目前正在使用 Google 地图的 InfoBox 插件 不幸的是 我遇到了一个恼人的问题 我的应用程序上的用户可以通过将鼠标悬停在相应的标记上来打开信息框 效果很好 当信息框打开并且用户将鼠标悬停在其上时 会出现此问题 由于某种原因 标
  • 使用 React 上传多个图像

    我想先通过预览来上传多张图像 然后提交以发送它们 我遇到过这样的情况 TypeError Cannot read property files of null 它还只允许我上传一张图像 我创造了files 作为在提交之前安装图像以供审核的方
  • Windows 7下如何设置进程超时?

    我想使用 Windows 批处理文件启动一个程序 但程序应该在一定的超时值后停止 例如 运行程序60秒 60秒后停止 Linux下有这个不错的timeout命令做我想做的事 Windows 也有一个timeout命令 但它只是暂停命令 延迟
  • 生成不重复的随机数。C# [重复]

    这个问题在这里已经有答案了 大家好 我试图在 C 的同一行上生成 6 个不同的数字 但我面临的问题是有些数字在同一行上重复 这是我的代码 var rand new Random List
  • 在 Mercurial 中,如何将反向补丁应用于特定文件?

    相关Mercurial 在一个存储库中的分支之间合并一个文件 https stackoverflow com questions 1078881 mercurial merging one file between branches in
  • 在 iPhone 应用程序中使用 CoreGraphic 描边作为 Alpha 遮罩

    我基本上希望为不同的目的创建类似于 iSteam iFog alebit 的非常简单版本的东西 实际上 将有两个图像 一个是主题图像 另一个是凝结图像或类似图像 然后 用户可以在屏幕上擦拭手指 它将从顶层 剪切 以显示下层 到目前为止 我已
  • 如何在IntelliJ IDEA中查看JDK外部文档?

    此操作的快捷方式是 Shift F1 但它始终呈灰色 即使我已指出 JDKdocumentation path to the docs文件夹 docs 文件夹解压自jdk 7u2 apidocs zip http www oracle co
  • matplotlib 中的交互线

    我正在尝试使用 matplotlib 制作一个交互式绘图 该绘图创建一个端点处带有两个句柄的线段 您可以单击并拖动手柄 线条将刷新以匹配以此方式指定的位置 与此 matplotlib 示例类似多编辑器 http matplotlib org
  • Java spring security - 拦截不同登录的子域url?

    我有一个安装了 spring security 且运行良好的应用程序 它目前已用完www exampledomain com 我现在想扩展在子域之外运行的应用程序 例如newapp exampledomain com 唯一的问题是 对于这个
  • 是否可以在 lambda 表达式中定位 EventHandler?

    举一个简单的例子 如果我有某种按钮 UI 类 我可以编写一个函数来接受指向其的表达式吗 Click事件处理程序 SomeMethod