Observable.FromEvent和CreateDelegate参数映射

12
我正在查看实现的代码。
Observable.FromEvent<TEventHandler, TEventHandlerArgs>(add, remove)

我很难理解它是如何工作的。假设TEventHandler是标准:

public delegate void EventHandler(object sender, EventArgs e);

我感到困惑的是下面的代码:

TEventHandler d = (TEventHandler) Delegate.CreateDelegate(
    typeof (TEventHandler),
    (object) new Action<EventArgs>(observer.OnNext),
    typeof (Action<EventArgs>).GetMethod("Invoke"));

(注意:我已经将这个通用代码专门应用于这个具体的示例实例。)

CreateDelegate是如何创建一个绑定到动作上的签名为(obj,args)、方法签名为(args)的委托?obj在哪里?

感觉有点像在动作上有一个开放式委托,并且我们正在从CreateDelegate中强制'this'成为'firstArgument',并允许参数透传。如果是这样的话,感觉有点不好?


2
你确定你有正确的代码吗?尝试一个简单的示例来模拟上面的调用,结果是:“无法绑定到目标方法,因为其签名或安全透明度与委托类型不兼容。” - casperOne
1
这是我用来重现上述错误的示例的要点:https://gist.github.com/4004086 - casperOne
1
我现在打算将此关闭为“过于局限”,因为您发布的内容似乎并不是框架中实际存在的内容;话虽如此,如果您有更多的研究证明它不是太过局限的,请标记该问题,我们会解锁它(假设它不再是太过局限)。 - casperOne
5
如果有人好奇的话,我在使用rx时使用了错误的方法。应该使用Observable.FromEventPattern,其实现方式与签名匹配非常合理。FromEvent用于不符合标准模式(obj,args)的事件! - DanH
请注意,Rx源代码现在已发布在http://rx.codeplex.com/。 - David Gardiner
显示剩余3条评论
1个回答

1

让我们分解一下:

首先,反编译 Rx v2.0.3 看起来没有 Observable.FromEvent<TEventHandler, TEventHandlerArgs>(add, remove) 方法,Rx v1.1 也没有。我偶然找到了一个最接近的匹配,我会假设你指的是我能找到的最接近的方法,就是这个:

public static IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler)

查看Rx 1.1的反编译源代码(2.0源代码已经变成了全是间接引用的架构宇航员,使得代码更难理解)。使用反编译器进行反编译的实际代码片段如下:

Action<TEventArgs> o = new Action<TEventArgs>(observer.OnNext);
    TDelegate d = CreateDelegate<TDelegate>(o,
        typeof(Action<TEventArgs>).GetMethod("Invoke"));

    addHandler(d);

所以问题是什么:
CreateDelegate 如何创建一个签名为(obj, args)的委托,并绑定到一个具有签名(args)的 action 的 invoke 方法上?obj 去哪了?
我不确定是否理解正确,但问题似乎特别是像“CreateDelegate(o, typeof(Action).GetMethod("Invoke")) 如何产生只有args参数的方法——发生了什么使得o对象不见了?”
发生的是,是的,o对象作为“object firstArgument”传递给内部的.NET框架方法。
public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method, bool throwOnBindFailure)

该方法将第一个参数“绑定”为返回方法的基本上是this指针。在委托对象内部,它将存储对第一个参数的引用。由于这是内部.NET实现细节,因此我们无法看到其中的内容,因此它可以执行各种奇怪的操作并违反规则。
引用块: 引用块: 感觉有点像在操作一个打开的操作的委托,并从CreateDelegate强制将'this'转换为'firstArgument',并允许参数通过。如果是这样感觉会有点肮脏?
是的,这几乎就是正在发生的事情。这就是CreateDelegate函数的设计目的。
除了它甚至变得更加肮脏。CreateDelegate只是返回一个类型为Delegate的对象-我们没有对方法参数等进行类型安全-check,然后代码将其转换为TDelegate-这适用于委派是特殊的,您可以将其转换为具有相同“形状”的任何函数类型。如上所述,这是内部.NET实现的细节,因此它可以执行各种奇怪的操作。 :-)

我意识到我的问题基于语法误解,因此使用不正确(如果您阅读原始评论,会提到这一点)。我想我应该明确地添加一个答案来关闭这个问题。感谢您的努力。我将把您标记为答案作为补偿 ;) - DanH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接