F#Expr.TryGetReflectedDefinition具有重载方法



我正在为FunScript项目编写一些扩展(F#到Javascript编译器)。如果你感兴趣,你可以在这里找到来源。

我试图模仿Tomas Petricek的AwaitObservable扩展。然而,如果我使用像AwaitObservable(w), AwaitObservable(w1,w2)...这样的重载方法,当我试图将项目编译为Javascript时,我会得到以下错误:

An unhandled exception of type 'System.Reflection.AmbiguousMatchException' occurred in FSharp.Core.dll
Additional information: Ambiguous match found.

FunScript在项目中保留一个反映定义的缓存字典,当它试图使用Expr.TryGetReflectedDefinition向缓存中添加一个新定义时,就会发生此错误。如果我使用不同的名称而不是重载(AwaitObservable2, AwaitObservable3...),错误就会消失。这是我现在使用的解决方法,但我想了解更多关于这个问题的信息,以及是否可以修复它,以便扩展的用户可以正常使用重载方法。

我可以想象F#中的Reflected Definitions不支持重载方法,并且不能仅通过参数的数量来区分方法(我无法检查,因为我在fsharp GitHub源代码库中没有找到Expr.TryGetReflectedDefinition的实现)。然而,让我困惑的是,当寻找AwaitObservable时,错误并没有发生,而是以下方法:

{System.IDisposableSystem IObservable 1-Subscribe(System.IObserver 1[FonScript.TypeScript.MouseEvent])}System.Reflection.MethodBase{System.Reflection.RuntimeMethodInfo}

所以我的问题是:

  1. 为什么Expr.TryGetReflectedDefinition在使用IObservable.Subscribe而不是Async.AwaitObservable时失败
  2. 为什么Expr.TryGetReflectedDefinition抛出异常而不是返回None
  3. 这是F#反射定义的一个错误还是不可避免的限制?有可能修理它吗

提前非常感谢您的帮助!

好吧,这似乎不是一个简单的答案,所以我会试着回答我自己的问题。经过进一步调查。。。

  1. 似乎由于Async.AwaitObservable过载,存储的反射定义不知何故(这个"不知何故"仍然无法解释)丢失了对实现IObservable的类型的跟踪,这就是为什么他们不知道应该使用Subscribe的哪个实现
  2. 我想这是有意的行为:返回None意味着没有找到Reflected Definition,但这里有一个不明确的匹配,所以情况不同
  3. 我还不知道这是一个bug还是一个"特性",但在任何情况下,我都使用CompiledName属性并为每个重载赋予不同的名称来解决这种特殊情况下的问题。现在一切正常:)

我希望下次我发布一个可以实际回答的问题时;)感谢所有花时间阅读这篇文章的人。

最新更新