有没有办法简化 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# 中的反射委托代码? 的相关文章

  • 创建 DirectoryEntry 实例以供测试使用

    我正在尝试创建 DirectoryEntry 的实例 以便可以使用它来测试将传递 DirectoryEntry 的一些代码 然而 尽管进行了很多尝试 我还是找不到实例化 DE 并初始化它的 PropertyCollection 的方法 我有
  • 属性对象什么时候创建?

    由于属性实际上只是附加到程序集的元数据 这是否意味着属性对象仅根据请求创建 例如当您调用 GetCustomAttributes 时 或者它们是在创建对象时创建的 或者 前两个的组合 在由于 CLR 的属性扫描而创建对象时创建 从 CLR
  • 在 Rails 中,我可以通过委托方法订购查询吗?

    我在通过委托方法订购查询时遇到困难 我的任务是帮助将一个相当大的 Rails 3 应用程序升级到 Rails 4 我在索引操作中遇到了这个查询 我知道这些对象的命名是可怕且令人困惑的 measurements controller rb d
  • 嵌入式系统中的malloc [重复]

    这个问题在这里已经有答案了 我正在使用嵌入式系统 该应用程序在 AT91SAMxxxx 和 cortex m3 lpc17xxx 上运行 我正在研究动态内存分配 因为它会极大地改变应用程序的外观 并给我更多的力量 我认为我唯一真正的路线是为
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 为什么 POSIX 允许在只读模式下超出现有文件结尾 (fseek) 进行搜索

    为什么寻找文件结尾很有用 为什么 POSIX 让我们像示例中那样在以只读方式打开的文件中进行查找 c http en cppreference com w c io fseek http en cppreference com w c io
  • c 中的错误:声明隐藏了全局范围内的变量

    当我尝试编译以下代码时 我收到此错误消息 错误 声明隐藏了全局范围内的变量 无效迭代器 节点 根 我不明白我到底在哪里隐藏或隐藏了之前声明的全局变量 我怎样才能解决这个问题 typedef node typedef struct node
  • .Net Core / 控制台应用程序 / 配置 / XML

    我第一次尝试使用新的 ConfigurationBuilder 和选项模式进入 Net Core 库 这里有很多很好的例子 https docs asp net en latest fundamentals configuration ht
  • 为什么模板不能位于外部“C”块内?

    这是一个后续问题一个答案 https stackoverflow com questions 4866433 is it possible to typedef a pointer to extern c function type wit
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • 网络参考共享类

    我用 Java 编写了一些 SOAP Web 服务 在 JBoss 5 1 上运行 其中两个共享一个类 AddressTO Web 服务在我的 ApplycationServer 上正确部署 一切都很顺利 直到我尝试在我的 C 客户端中使用
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • char指针或char变量的默认值是什么[重复]

    这个问题在这里已经有答案了 下面是我尝试打印 char 变量和指针的默认值 值的代码 但无法在控制台上看到它 它是否有默认值或只是无法读取 ASCII 范围 include
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • Bing 地图运行时错误 Windows 8.1

    当我运行带有 Bing Map 集成的 Windows 8 1 应用程序时 出现以下错误 Windows UI Xaml Markup XamlParseException 类型的异常 发生在 DistanceApp exe 中 但未在用户
  • 如何使用 ReactiveList 以便在添加新项目时更新 UI

    我正在创建一个带有列表的 Xamarin Forms 应用程序 itemSource 是一个reactiveList 但是 向列表添加新项目不会更新 UI 这样做的正确方法是什么 列表定义 listView new ListView var
  • 将变量分配给另一个变量,并将一个变量的更改反映到另一个变量中

    是否可以将一个变量分配给另一个变量 并且当您更改第二个变量时 更改会瀑布式下降到第一个变量 像这样 int a 0 int b a b 1 现在 b 和 a 都 1 我问这个问题的原因是因为我有 4 个要跟踪的对象 并且我使用名为 curr
  • C++ 成员函数中的“if (!this)”有多糟糕?

    如果我遇到旧代码if this return 在应用程序中 这种风险有多严重 它是一个危险的定时炸弹 需要立即在应用程序范围内进行搜索和销毁工作 还是更像是一种可以悄悄留在原处的代码气味 我不打算writing当然 执行此操作的代码 相反
  • 不同类型的指针可以互相分配吗?

    考虑到 T1 p1 T2 p2 我们可以将 p1 分配给 p2 或反之亦然吗 如果是这样 是否可以不使用强制转换来完成 或者我们必须使用强制转换 首先 让我们考虑不进行强制转换的分配 C 2018 6 5 16 1 1 列出了简单赋值的约束

随机推荐

  • 将 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