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

馋奶兔 提交于 2019-12-12 18:25:05

问题


I'm trying to use PowerShell to call some F# code which uses Akka.Net actors.

The F# code works fine in unit testing and when run from the F# interpreter, but when I call the same code from a PowerShell cmdlet I get the following exception:

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()

I tried running [Nessos.FsPickler.BinarySerializer]::new.OverloadDefinitions in that PowerShell session to check what methods PS though was available and I get:

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

First thing I noticed was that the version shown by PowerShell takes an FSharpOption[bool] instead of FSharpOption[Boolean]. I tried modifying the Akka.FSharp code to explcitly pass an Option, but that didn't seem to help.

I'm using FSharp.Core 4.0.0.1 (other links suggested 3.0 had problems).

Has anyone seen anything similar?

Even suggestions about where to look for the problem would be helpful, I'm not sure if the issue is with PowerShell, F# or Akka.Net.


回答1:


Powershell can be difficult when it comes to matching methods based on parameter types. I've found that sometimes i have to "trick" PS by passing an expression to a method rather than a PS variable. For example $object.method($something.property) instead of $prop = $something.property; $object.method($prop) has worked for me.

In the case of overloaded methods another thing you can do is use Reflection to make sure you've got the method with the right signature. For example:

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

And sometimes casting helps: $object.method([typeToMatchMethodSig]$arg1) or maybe even a double cast:$object.method([bool][int]$arg1) In both cases I think you'll have more luck if you pass the cast expression as an argument, rather than assign it to a variable and pass the variable.

I doubt this is the case in the OP, but using [activator]::createinstance(...) can be used with a private constructor.

I usually muck around with it till either something works or I give up.

BTW, you can turn on PS tracing for parameter binding and get a lot of info, which may or may not be useful.



来源:https://stackoverflow.com/questions/33696325/why-am-i-getting-a-missingmethodexception-when-calling-f-code-from-powershell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!