【问题标题】:Why am I getting a MissingMethodException when calling F# code from PowerShell?为什么从 PowerShell 调用 F# 代码时会出现 MissingMethodException?
【发布时间】:2016-03-29 20:34:56
【问题描述】:

我正在尝试使用 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 会话中运行 [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 上。

【问题讨论】:

  • 根据我的经验MissingMethodException 总是由版本问题引起的。您的 PowerShell 会话很可能最终会加载与您的代码最初编译时所针对的程序集不同的版本。最好的办法是使用 fuslogvw 解决程序集绑定问题msdn.microsoft.com/en-us/library/e74a18c4
  • fuslogvw 原来是一个好的开始。没有解决问题,但至少让我诊断一下。事实证明,Akka.FSharp 和 FsPickler 是针对不同版本的 FSharp.Core 构建的。在常规项目中,您可以使用绑定重定向的魔力来掩盖这些差异,但这在 PowerShell 中并不容易。最后我听从了@user2470798 的建议,放弃了重新设计了一些东西,所以我不直接从 PowerShell 调用 Akka。

标签: powershell f# akka.net missingmethodexception assembly-loading


【解决方案1】:

当涉及到基于参数类型的匹配方法时,Powershell 可能会很困难。我发现有时我必须通过将表达式传递给方法而不是 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追踪,得到很多信息,可能有用也可能没用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-08
    • 1970-01-01
    • 1970-01-01
    • 2019-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多