Observable.FromEvent和CreateDelegate param映射

Dan*_*anH 12 c# delegates system.reactive

我正在考虑实施

Observable.FromEvent<TEventHandler, TEventHandlerArgs>(add, remove)
Run Code Online (Sandbox Code Playgroud)

我正在努力把握它是如何运作的.让我们说TEventHandler是标准:

public delegate void EventHandler(object sender, EventArgs e);
Run Code Online (Sandbox Code Playgroud)

那令我困惑的代码是:

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

(我已将此通用代码专门用于此特定示例实例.)

CreateDelegate是如何创建一个签名委托(obj,args)绑定到动作上的签名(args)的调用方法?obj去哪儿了?

感觉有点像在行动中有一个开放的代表,我们正在强迫'this'成为CreateDelegate的'firstArguemnt'并允许args通过.如果这样感觉有点脏?

Ori*_*rds 1

让我们来分解一下:

首先,反编译Rx v2.0.3似乎没有Observable.FromEvent<TEventHandler, TEventHandlerArgs>(add, remove)方法,我碰巧拥有的Rx v 1.1也没有。我假设您指的是我能找到的最接近的匹配项,即:

public static IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler)
Run Code Online (Sandbox Code Playgroud)

查看 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);
Run Code Online (Sandbox Code Playgroud)

那么,问题是:

CreateDelegate 如何创建签名 (obj, args) 的委托,该委托绑定到操作上签名 (args) 的调用方法?obj要去哪里?

我不确定我的理解是否完全正确,但问题似乎具体是如何CreateDelegate<TDelegate>(o, typeof(Action<TEventArgs>).GetMethod("Invoke")生成仅包含参数的方法args- 对象会发生什么o

所发生的情况是,o对象正在被传递object firstArgument给内部 .NET 框架方法。

public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method, bool throwOnBindFailure)
Run Code Online (Sandbox Code Playgroud)

此方法将firstArgument“绑定”为基本上作为this返回方法的指针。在内部,它将存储对委托对象内某处的firstArgument 的引用。我们无法看到其内部,因为它是内部 .NET 实现细节,因此它可以做各种奇怪的事情并随心所欲地违反规则。

感觉有点像在操作上有一个开放的委托,我们正在将“this”强制为 CreateDelegate 的“firstArguemnt”,并允许参数失败。如果这样感觉有点脏吗?

是的,这几乎正是正在发生的事情。这就是该CreateDelegate函数的设计目的。
但它变得比那更脏。CreateDelegate只是返回一个类型的对象Delegate- 我们在方法参数等上没有类型安全 - 然后代码将其转换为 a TDelegate- 这是有效的,因为委托是特殊的,您可以将其转换为具有相同“形状”的任何函数类型。如上所述,它是一个内部 .NET 实现细节,因此它可以做各种奇怪的事情:-)