有没有办法简化 C# 中的反射委托代码?

2024-04-18

In this https://stackoverflow.com/a/12867132/171121回应,我想出了以下辅助方法,可以被不同的人重用Task创建者将事件转换为任务完成源。

// Helper method
static Task<T> TaskFromEventHelper<T>(object target, string eventName, Func<TaskCompletionSource<T>, object> resultSetterFactory) {
    var tcs = new TaskCompletionSource<T>();
    var addMethod = target.GetType().GetEvent(eventName).GetAddMethod();
    var delegateType = addMethod.GetParameters()[0].ParameterType;
    var d = Delegate.CreateDelegate(delegateType, resultSetterFactory(tcs), "Invoke");
    addMethod.Invoke(target, new object[] {d});
    return tcs.Task;
}

// Empty events (Action style)
static Task TaskFromEvent(object target, string eventName) {
    return TaskFromEventHelper(target, eventName, (Func<TaskCompletionSource<object>, object>)(tcs => (Action)(() => tcs.SetResult(null))));
}

// One-value events (Action<T> style)
static Task<T> TaskFromEvent<T>(object target, string eventName) {
    return TaskFromEventHelper(target, eventName, (Func<TaskCompletionSource<T>, object>)(tcs => (Action<T>)(tcs.SetResult)));
}

// Two-value events (Action<T1, T2> or EventHandler style)
static Task<Tuple<T1, T2>> TaskFromEvent<T1, T2>(object target, string eventName) {
    return TaskFromEventHelper(target, eventName, (Func<TaskCompletionSource<Tuple<T1, T2>>, object>)(tcs => (Action<T1, T2>)((t1, t2) => tcs.SetResult(Tuple.Create(t1, t2)))));
}

在我给出的使用辅助方法的三个示例中,每个示例都有一个tcs.SetResult组件,这让我认为也有一种方法可以将其移动到辅助方法中,这可能会简化签名,这样辅助方法可能只需要接受Func<?, T>,其中Func将采取的输出event并将其转换为任何内容tcs.SetResult需要。

即,我认为必须有一种方法来创建一个助手,这样我就可以将其写为

// Empty events (Action style)
static Task TaskFromEvent(object target, string eventName) {
    return TaskFromEventHelper<object>(target, eventName, new Func<object>(() => null));
}

// One-value events (Action<T> style)
static Task<T> TaskFromEvent<T>(object target, string eventName) {
    return TaskFromEventHelper<T>(target, eventName, new Func<T, T>(t => t));
}

// Two-value events (Action<T1, T2> or EventHandler style)
static Task<Tuple<T1, T2>> TaskFromEvent<T1, T2>(object target, string eventName) {
    return TaskFromEventHelper<Tuple<T1, T2>>(target, eventName, new Func<T1, T2, Tuple<T1, T2>>(Tuple.Create));
}

,但这就是为什么我不知道? in Func<?, T>多于。例如这个需要? to be two参数。是否可以传入为object不知何故?我有一种感觉,这是可能的,但如果是这样,它需要一些真正的反射魔法。


您可以使用Expression:

static Task<T> TaskFromEventHelper<T>(object target, string eventName, Delegate resultSetter)
{
    var tcs             = new TaskCompletionSource<T>();
    var addMethod       = target.GetType().GetEvent(eventName).GetAddMethod();
    var delegateType    = addMethod.GetParameters()[0].ParameterType;
    var methodInfo      = delegateType.GetMethod("Invoke");
    var parameters      = methodInfo.GetParameters()
                                    .Select(a => Expression.Parameter(a.ParameterType))
                                    .ToArray();

    // building method, which argument count and
    // their types are not known at compile time
    var exp = // (%arguments%) => tcs.SetResult(resultSetter.Invoke(%arguments%))
        Expression.Lambda(
            delegateType,
            Expression.Call(
                Expression.Constant(tcs),
                tcs.GetType().GetMethod("SetResult"),
                Expression.Call(
                    Expression.Constant(resultSetter),
                    resultSetter.GetType().GetMethod("Invoke"),
                    parameters)),
            parameters);

    addMethod.Invoke(target, new object[] { exp.Compile() });
    return tcs.Task;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有没有办法简化 C# 中的反射委托代码? 的相关文章

  • 高级 Win32 图像文件 I/O?

    我想在 Windows C 应用程序中将图像文件读入内存 什么是一个相当简单的解决方案 也许类似于 IOS 提供的UIImage 我希望支持合理数量的文件格式 我需要为图像处理的位图提供一些低级访问权限 我在互联网上阅读了很多内容 看起来
  • 如何知道并加载特定文件夹中的所有图像?

    我有一个应用程序 C Builder 6 0 需要知道特定文件夹中的图像总数 然后我必须加载它们 在 ImageList 或 ComboBoxEx 中 或任何其他控件中 我怎样才能做到这一点 我知道如何在控件中加载图像 或保存在 TList
  • LINQ to XML - 如何正确使用 XDocument

    现在我首先要说的是 这确实是一项任务 然而 在我遇到 Linq to XML 语法之前 我几乎已经完成了它 我有 2 个课程 曲目和 CD 现在作为作业的一部分 我创建了一张 CD 然后向其中添加了一些曲目 在搜索了大量完美解释了如何从 x
  • 将 2D 数组映射到 1D 数组

    我想用一维数组来表示一个二维数组 函数将传递两个索引 x y 和要存储的值 这两个索引代表一维数组的单个元素 并相应地设置它 我知道一维数组需要具有 arrayWidth arrayHeight 的大小 但我不知道如何设置每个元素 例如 如
  • Linq Where 本地计数器关闭在 VS watch 中的结果不同

    我尝试删除前 3 个元素array与 LinQWhere扩展功能 这是一个例子 var array new 1 2 3 4 5 6 7 8 9 var count 3 var deletedTest1 0 var test1 array W
  • 如何避免选择项目时 winforms 树视图图标发生变化

    我正在一个小型 C Winforms 应用程序中尝试树视图 我已经以编程方式将 ImageList 分配给树视图 并且所有节点都很好地显示了它们的图标 but当我单击一个节点时 它的图标会发生变化 变为 ImageList 中的第一个图像
  • C中有const吗?

    这个问题可能很幼稚 但是 有没有constC 中的关键字 从哪个版本开始 之间有任何语义和 或句法差异吗const在 C 和 C 中 C 和 C 之间在语法上没有差异const关键字 除了一个相当晦涩的关键字 在 C 中 自 C99 起 您
  • 根据拦截和返回值自动重试客户端WCF调用

    是否可以拦截 WCF 调用的结果并重试该操作 例如 操作的返回值可能包含状态代码 指示我传递到原始调用的会话令牌已过期 在这种情况下 我可以检索新的会话令牌并使用新的会话令牌重试调用 是否可以通过使用 WCF 拦截返回值 检查它 然后以对操
  • 捕获当前正在播放的声音

    是否可以捕获计算机上当前播放的声音 如果能够将其保存为 mp3 就好了 但我认为这样做会存在一些法律问题 所以 wav 也可以 我环顾四周 有人建议使用虚拟音频线之类的东西 在 C 中捕获声音输出 https stackoverflow c
  • CMake - 将预构建库链接到 C# 项目

    我正在使用 CMake 构建 C 库 该库依赖于已构建的库 dll 我似乎无法让图书馆链接到我的图书馆 我尝试过使用target link libraries mylib external lib 我也尝试过暴力破解 reference e
  • 在可观察项目生成时对其进行处理

    我有一个IObservable它会生成一次性物品 并且在其生命周期内可能会生成无限数量的物品 因此 我想在每次生成新项目时处理最后一个项目 因此Using http reactivex io documentation operators
  • 使用 Linq 进行异步Where过滤

    我有一个List通过填充的元素async调用 WebService 没问题 我需要过滤该列表以便在应用程序视图上显示某些内容 我试过这个 List
  • 改进C++逐行读取文件的能力?

    我正在解析大约 500GB 的日志文件 我的 C 版本需要 3 5 分钟 我的 Go 版本需要 1 2 分钟 我正在使用 C 的流来流式传输文件的每一行以进行解析 include
  • 在 MVVM 中,可以在视图后面的代码中访问 ViewModel 吗?

    在 MVVM 模式中 是否可以接受甚至可以访问视图代码后面的 ViewModel 属性 我有一个可观察的集合 它填充在 ViewModel 中 我需要在视图中使用它来绑定到带有链接列表的无限滚动条 IE private LinkedList
  • 宏观评价[重复]

    这个问题在这里已经有答案了 可能的重复 未定义的行为和序列点 https stackoverflow com questions 4176328 undefined behavior and sequence points 我无法理解以下宏
  • 如何使复选框不可选择?

    我想知道你是怎么做的CheckBox在c 中无法选择 我认为这会是类似 SetSelectable false 之类的东西 但我似乎看不到该方法 I found CanSelect但这似乎是只读属性 您可以设置自动检查 http msdn
  • 如何仅更改 DateTime 的日期部分,同时保留时间部分?

    我在代码中使用了很多 DateTime 我想将这些日期时间更改为我的特定日期并保留 时间 1 2012 02 02 06 00 00 gt 2015 12 12 06 00 00 2 2013 02 02 12 00 00 gt 2015
  • Windows 上 libcurl 的静态库[重复]

    这个问题在这里已经有答案了 如何将此库 libcurl 静态链接到 exe 我努力了 disable share enable static 没有帮助 我使用的是MingW32 有没有一种简单的方法来静态链接这个库 这样我的应用程序就不再有
  • ASP.NET Core:会话 ID 始终变化

    今天启动了一个全新的 ASP NET Core 网站 按照说明添加会话 我们在索引页上打印出会话 ID 它始终是唯一的 我认为这可能是 cookie 合规性 所以我在 Chrome 的高级设置和调试器中删除了所有 cookie 但横幅不会再
  • 当我读取 500MB FileStream 时出现 OutOfMemoryException

    我使用 Filestream 读取大文件 gt 500 MB 但出现 OutOfMemoryException 任何有关它的解决方案 我的代码是 using var fs3 new FileStream filePath2 FileMode

随机推荐

  • 将 lambda 函数应用于 dask 数据框

    我正在寻找申请lambda如果列中的标签小于一定百分比 则使用 dask 数据框的函数来更改列中的标签 我使用的方法适用于 pandas 数据框 但相同的代码不适用于 dask 数据框 代码如下 df pd DataFrame A ant
  • 将多个单元格添加到单行

    我对此很陌生 当我尝试将多个单元格添加到一行时 它说有不可读的内容 这是我所拥有的 SpreadsheetDocument ssDoc SpreadsheetDocument Create saveFile SpreadsheetDocum
  • 作为单独用户运行应用程序的最佳初始化脚本

    我有一个在用户帐户 基于 Plack 中运行的应用程序 并且需要一个初始化脚本 它看起来就像 sudo user start server 一样简单 我刚刚使用 start stop daemon 编写了一个 LSB 脚本 它确实很笨拙且冗
  • Apple HLS 中的 PES 数据包内的访问单元如何对齐?

    Apple 是否指定了这一点 PES 数据包有效负载中应放置多少个访问单元 另外 我想知道 PES 数据包中存在哪些前缀起始代码 如果有 我认为访问单元中第一个 NAL 单元之前的单元是无用的 不能放置 正确的 我想知道它是如何在 HLS
  • 使用 PHPUnit 和 Selenium 设置测试

    您能帮我设置测试环境吗 我在 Ubuntu 上运行 安装了 并运行 selenium Web 服务器 并通过 PHPUnit 执行我的测试 最有可能的是我陷入了一些小错误 但我现在不知道如何修复它 我的代码很简单 class WebTest
  • WPF Square 自动调整父容器大小

    我有一个UniformGrid我的 WPF 项目中的对象有 2 行和 3 列 其宽度和高度设置为自动 两种对齐方式都设置为拉伸 该网格将容纳 6squares我想尽可能多地填充他们的单元格 并水平和垂直居中 我需要添加什么才能允许方块根据父
  • 如何在localStorage中存储数组?

    我有一个数据属性 data return playWord baseWord result 并回应 baseWord Amazing 每次我在 api 中发送新请求时 基本词都会发生变化 我想将每个数据存储在本地存储中并将字符串值发送到 a
  • 具有区域格式的 NSDateFormatter

    我使用此代码来处理来自 json feed 的日期字符串 NSDateFormatter formatter NSDateFormatter alloc init formatter setDateStyle NSDateFormatter
  • 如何让 gif 动画在 WPF 中工作?

    我应该使用什么控制类型 Image MediaElement etc 我无法得到这个问题的最流行的答案 上面由达里奥 正常工作 结果是奇怪的 断断续续的动画和奇怪的伪影 到目前为止我找到的最佳解决方案 https github com Xa
  • Hibernate:是否可以在二级缓存中保存瞬态字段?

    我需要跟踪持久实体的字段 该字段会经常更改 并且实际上并不是该实体的功能 而是某种计算 有时 用户希望查看该计算结果 但这种情况非常罕见 每月一次左右 因此 必须以某种方式保存此计算的结果 但我想避免每次更改时都将其保存在数据库中 因为这每
  • “找不到类‘android.support.v4.app.FragmentActivity’”错误

    我收到以下错误 gt 02 06 23 10 24 104 E dalvikvm 912 Could not find class gt android support v4 app FragmentActivity referenced
  • 如何使用SVM求精确率、召回率、准确率?

    重复计算 Precision Recall 和 F Score https stackoverflow com questions 16927964 how to calculate precision recall and f score
  • 在 Yii 的视图中我应该更喜欢使用 widget 还是 renderPartial?

    当我应该在视图文件中使用自定义小部件或 renderPartial 时 我很困惑 有时我使用 widget 有时我使用 renderPartial Widget You use widget当您的应用程序逻辑定义在单独的类文件并且逻辑在某种
  • 将 C 字符串数组传递给 Fortran (iso_c_binding)

    如何传递 C 字符串数组 char cstrings 到 Fortran 子程序 问题使用 iso c binding 的 fortran C 桥接器中的字符串数组 https stackoverflow com questions 968
  • 在 Windows 上使用 PHP 获取总可用系统内存

    使用 PHP 我想获取系统可用的总内存 而不仅仅是空闲或已用内存 在 Linux 上 这非常简单 你可以做 memory fopen proc meminfo 然后解析该文件 有人知道 Windows 的等效方法吗 我愿意接受任何建议 编辑
  • 通过 UIPanGestureRecognizer 传递点击

    我想检测整个屏幕上的滑动 但是 屏幕包含UIButtons 如果用户点击这些按钮之一 我希望触发 Touch Up Inside 事件 我创建了一个UIView在我的屏幕顶部 并添加了一个UIPanGestureRecognizer在其上检
  • Qt 线程阻止 UI 响应

    我想我可能误解了Qt线程中的几个概念 在我的窗口类中 它派生自 QWidget class Widget Q OBJECT public Widget Widget QObject parent 0 QObject parent moveT
  • XNA 数字锁定影响输入

    我有一个中断 在键盘按键上给我协调键 当数字锁打开时 按键会显示为 Numpad1 Numpad2 等 当数字锁关闭时 数字键盘键会变成 End Left Right Up PageLock 我不能让这种情况发生 因为我需要将这些键 左 右
  • 确定 iPhone 上的互联网可用性?

    我在 iPhone 应用程序中使用 NSURLConnection 如下所示 NSURLConnection conn NSURLConnection alloc initWithRequest request delegate self
  • 有没有办法简化 C# 中的反射委托代码?

    In this https stackoverflow com a 12867132 171121回应 我想出了以下辅助方法 可以被不同的人重用Task创建者将事件转换为任务完成源 Helper method static Task