从 PowerShell 调用 F# 代码时,为什么会出现 MissingMethodException?

Why am I getting a MissingMethodException when calling F# code from PowerShell?

我正在尝试使用 PowerShell 调用一些使用 Akka.Net 参与者的 F# 代码。

F# 代码在单元测试中以及在 F# 解释器 运行 中工作正常,但是当我从 PowerShell cmdlet 调用相同的代码时,出现以下异常:

System.MissingMethodException: Method not found: 'Void Nessos.FsPickler.BinarySerializer..ctor(Microsoft.FSharp.Core.FSharpOption`1<Boolean>, 
                    Microsoft.FSharp.Core.FSharpOption`1<Nessos.FsPickler.ITypeNameConverter>)'.
                       at Akka.FSharp.Serialization.ExprSerializer..ctor(ExtendedActorSystem system)
                       at Akka.FSharp.Serialization.exprSerializationSupport(ActorSystem system)
                       at Namespace.NewActorCmdlet..ctor(Host hostA, Host hostB, Boolean option, UserDetails user) in 
                    E:\Projects\Namespace\NewActorCommand.fs:line 24
                       at Namespace.StartNewActorCommand.ProcessRecord() in 
                    E:\Projects\Namespace\StartNewActor.fs:line 67
                       at System.Management.Automation.CommandProcessor.ProcessRecord()

我在该 PowerShell 会话中尝试 运行ning [Nessos.FsPickler.BinarySerializer]::new.OverloadDefinitions 来检查哪些方法 PS 可用,我得到:

Nessos.FsPickler.BinarySerializer new(Microsoft.FSharp.Core.FSharpOption[bool] forceLittleEndian, Microsoft.FSharp.Core.FSharpOption[Nessos.FsPickler.ITypeNameConverter] typeConverter)

我注意到的第一件事是 PowerShell 显示的版本采用 FSharpOption[bool] 而不是 FSharpOption[Boolean]。我尝试修改 Akka.FSharp 代码以明确传递一个选项,但这似乎没有帮助。

我使用的是 FSharp.Core 4.0.0.1(其他链接提示 3.0 有问题)。

有人见过类似的东西吗?

即使是有关在何处查找问题的建议也会有所帮助,我不确定问题是否出在 PowerShell、F# 或 Akka.Net 上。

Powershell 在根据参数类型匹配方法时可能会很困难。我发现有时我必须 "trick" PS 通过将表达式传递给方法而不是 PS 变量。例如 $object.method($something.property) 而不是 $prop = $something.property; $object.method($prop) 对我有用。

对于重载方法,您可以做的另一件事是使用反射来确保您拥有具有正确签名的方法。例如:

$mi=$object.gettype().getmethod('TheMethod',@([typeParm1],[typeParm2]))
$mi.invoke($object, @($arg1,$arg2))

有时转换会有所帮助:$object.method([typeToMatchMethodSig]$arg1) 甚至可能是双重转换:$object.method([bool][int]$arg1) 在这两种情况下,我认为如果将转换表达式作为参数传递,而不是将它赋值给一个变量并传递变量。

我怀疑 OP 中的情况是否如此,但使用 [activator]::createinstance(...) 可以与私有构造函数一起使用。

我通常会弄乱它,直到某件事情奏效或我放弃为止。

顺便说一句,您可以打开 PS 跟踪参数绑定并获取大量信息,这些信息可能有用也可能没有用。