c# - 旧版 API 需要将回调名称作为字符串传递。我可以通过扩展方法改进该 API 吗?

标签 c# reflection

我面临着一个不使用 .NET 事件的遗留 API,而是要求我这样做:

// (first arg is System.Object, second arg is string, myFoo is of type Foo)
myFoo.AddCallback(this, "DoSomething(int)");

此 API 要求 DoSomethingthis 上的实例方法,并且它需要一个 int。

有没有办法可以强制此 API 以类型安全的方式使用?

更准确地说:我想为 Foo 编写一个扩展方法,它允许我使用 .NET 委托(delegate)(而不是接收者签名对)调用 AddCallback。我正在想象这样的事情:

// extension method definition
public static void AddCallback(this Foo foo, Action action)
{
    foo.AddCallback(
        FigureOutReceiverOf(action),    // ?
        FigureOutSignatureOf(action));  // ?
}

public static void AddCallback<T>(this Foo foo, Action<T> action)
{ ... } // and so on, for up to, say, 10 type-arguments

// usage:
myFoo.AddCallback(DoSomething)
// or even a lambda:
myFoo.AddCallback((i) => Console.WriteLine(i));

如果可以通过扩展方法 hack 来做到这一点,那会让我的生活变得更好。另外,我只是感兴趣是否可以考虑到 C# 的功能。

顺便说一下,旧版 API 称为 qt4dotnet。

最佳答案

使用 lambda 会很棘手 - 如果它捕获局部变量,它最终将成为不同类中的方法。当然,您可以检测到这一点,但编译时并不安全。

同样,签名部分很有趣,因为如果它绝对是一个操作,则委托(delegate)没有参数。您不能只让参数Delegate,否则方法组转换将不起作用...尽管您仍然可以调用

myFoo.AddCallBack(new Action<int>(MyMethodName));

另一种方法是产生一堆重载:

public static void AddCallback(this Foo foo, Action action)

public static void AddCallback<T>(this Foo foo, Action<T> action)

public static void AddCallback<T1, T2>(this Foo foo, Action<T1, T2> action)

这并不优雅,但出于实际原因您可能只需要一些。如果有任何方法返回值,您需要为 Func 提供类似的值。

传递具有多个操作的委托(delegate)还有一个额外的潜在问题...同样,您可以在编译时检查这一点。最后,您可能需要检查委托(delegate)的 Target 是否与 foo 参数相同。

解决了这些问题后,计算签名就变得相对简单了。您可以使用 Delegate.Method 属性,从中您可以获取名称和参数类型。如果库需要 "int" 而不是 "System.Int32" 等,那么您将需要对此进行一些处理,但这应该不会太糟糕。 (不过,这听起来确实是一个相当奇怪的 API。)

关于c# - 旧版 API 需要将回调名称作为字符串传递。我可以通过扩展方法改进该 API 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3732939/

相关文章:

json - 记录的简单 JSON 反序列化不正确(Delphi Sydney [10.4.1])

reflection - 尚不支持左侧为空的 Kotlin 类文字?

c# - 为什么参数化通用接口(interface)的 GetMethods() 返回非参数化 MethodInfo

java - 在运行时用类对象定义泛型类型

java - 获取类实例变量并使用反射打印它们的值

c# - 将锯齿状的 int[][] 数组转换为 object[][] 数组

c# - 简单的自定义 Web 控件

c# - 如何检测平板电脑(任何)请求?

c# - JavaScript 正则表达式问题

c# - 如何防止列表中的项目在未填写且应为 "0"时返回 "null"?