1

我正在为 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# 中的反射定义不支持重载方法,并且不能仅通过参数的数量来区分方法(我无法检查,因为我没有Expr.TryGetReflectedDefinition在 fsharp GitHub 源存储库中找到实现)。但是,令我困惑的是,在寻找 AwaitObservable 时并没有发生错误,而是以下方法:

{System.IDisposable System-IObservable 1-Subscribe(System.IObserver1[FunScript.TypeScript.MouseEvent])} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}

所以我的问题是:

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

非常感谢您的帮助!

4

1 回答 1

0

好的,这似乎没有简单的答案,所以我会尝试回答我自己的问题。经过进一步调查...

  1. 似乎由于Async.AwaitObservable重载,存储的反射定义以某种方式(这个“不知何故”仍然无法解释)失去了实现类型的跟踪,IObservable这就是为什么他们不知道Subscribe应该使用哪个实现。
  2. 我想这是预期的行为:返回None意味着尚未找到反映的定义,但这里有一个模棱两可的匹配,所以这是另一种情况。
  3. 我还不知道这是一个错误还是一个“功能”,但无论如何我在这种特殊情况下使用CompiledName属性修复了问题,并为每个重载提供了不同的名称。现在一切正常:)

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

于 2014-09-09T08:22:09.130 回答