我在测试解决方案中有3个项目:
在类库中我定义了一个akka.net actor:
namespace Just.Test.Project
open Akka.Actor
open Akka.FSharp
open Akka.Configuration
module Actors =
let system = System.create "WaveNetSystem" (Configuration.defaultConfig())
let simple = spawn system "simple" (fun mailbox ->
let rec loop() = actor {
let! message = mailbox.Receive()
printfn "%A" message
return! loop()
}
loop()
)
type MainClass(msg) = let x = Actors.simple <! msg
如果我从f#console应用程序中实例化MainClass
,我得到预期的结果:
[<EntryPoint>]
let main argv =
Just.Test.Project.MainClass("bugaga!") |> ignore
System.Threading.Thread.Sleep(1000)
0 // return an integer exit code
输出:
"bugaga!!!"
但是。如果我从c#console app那里做同样的事情:
static void Main(string[] args)
{
new Just.Test.Project.MainClass("bugaga!");
System.Threading.Thread.Sleep(1000);
}
我得到一个例外:
System.TypeInitializationException: The type initializer for '<StartupCode$SampleFSharpAkkaNet>.$Test' threw an exception. ---> System.MissingMethodException: Method not found: 'Akka.Actor.IActorRef Akka.FSharp.Spawn.spawn(Akka.Actor.IActorRefFactory, System.String, Microsoft.FSharp.Core.FSharpFunc`2<Actor`1<!!0>,Cont`2<!!0,!!1>>)'.
at <StartupCode$SampleFSharpAkkaNet>.$Test..cctor()
--- End of inner exception stack trace ---
at Just.Test.Project.Actors.get_simple()
at Just.Test.Project.MainClass..ctor() in d:\prj\research\AkkaFSharpTest\SampleFSharpAkkaNet\Test.fs:line 20
我该如何解释这个例外?什么可能是错的?
更新
正如评论和Tomas Petricek的回答中所述,该问题与版本不匹配有关。 bindingRedirect
完成工作,一切都开始工作。但我仍然有一些误解。
首先。 Akka.FSharp
引用FSharp.Core 4.3.1
。
二。 F#Lib和F#控制台引用FSharp.Core 4.4.0
,C#控制台根本没有引用FSharp.Core
。
第三。 F#控制台就像一个魅力,如果我打印加载的程序集,我得到:
FSharpConsole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
FSharpLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
FSharp.Core, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Akka, Version=1.0.6.16, Culture=neutral, PublicKeyToken=null
Akka.FSharp, Version=1.0.6.16, Culture=neutral, PublicKeyToken=null
FsPickler, Version=1.2.21.0, Culture=neutral, PublicKeyToken=null
System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
所以,没有FSharp.Core 4.3.1.0
加载,一切都是tip-top!
四。 C#控制台不起作用。加载的程序集列表看起来有点奇怪:
CSharpConsole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
FSharpLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
FSharp.Core, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
FSharp.Core, Version=4.3.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Akka, Version=1.0.6.16, Culture=neutral, PublicKeyToken=null
Akka.FSharp, Version=1.0.6.16, Culture=neutral, PublicKeyToken=null
这意味着FSharp.Core, Version=4.4.0.0
和FSharp.Core, Version=4.3.1.0
都已加载。为什么?为什么在F#Console案件中没有发生这种情况?
解
问题(通常))在我脑海中。
首先,我从未研究过最终的F#Console配置。最初的app.config
非常简单:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
但是在构建之后(感谢AutoGenerateBindingRedirects MSBuild flag)获得了所需的buinding重定向:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.4.0.0" newVersion="4.4.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
第二个。 C#编译器试图通过在构建输出中编写这样的消息来通知我这个问题:
无法解决&#34; FSharp.Core,Version = 4.3.1.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a&#34;之间的冲突。和&#34; FSharp.Core,Version = 4.3.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a&#34;。选择&#34; FSharp.Core,Version = 4.3.1.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a&#34;随意。 考虑app.config重新映射程序集&#34; FSharp.Core,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a&#34;来自版本&#34; 4.3.1.0&#34; [C:\ Program Files(x86)\ Reference Assemblies \ Microsoft \ FSharp.NETFramework \ v4.0 \ 4.3.1.0 \ FSharp.Core.dll] to Version&#34; 4.4.0.0&#34; [C:\ Program Files(x86)\ Reference Assemblies \ Microsoft \ FSharp.NETFramework \ v4.0 \ 4.4.0.0 \ FSharp.Core.dll]解决冲突并摆脱警告。 C:\ Program Files(x86)\ MSBuild \ 14.0 \ bin \ Microsoft.Common.CurrentVersion.targets(1820,5):警告MSB3276:发现同一依赖程序集的不同版本之间存在冲突。请设置&#34; AutoGenerateBindingRedirects&#34;项目文件中的属性为true。有关详细信息,请参阅http://go.microsoft.com/fwlink/?LinkId=294190。
但我认为C#编译器只是比F#编译器更具限制性。我不知道在F#项目中标志是自动设置的。什么阻止我检查它?我不知道! )
答案 0 :(得分:3)
这听起来像FSharp.Core.dll
版本不匹配问题。
最有可能的是,您引用的是FSharp.Core.dll
的较新版本,而不是Akka.net的F#包装器库所引用的版本。您可以引用相同的版本,也可以使用bindingRedirect
添加配置文件。请参阅Mark Seemann's blog post。
这里的关键字是MethodMissingException
- 你得到的是因为方法的签名涉及来自FSharp.Core.dll
的类型,并且已经加载的版本(基于C#项目中的引用)没有匹配包装器公开的版本(基于编译包装器时使用的引用)。由于版本不匹配,类型被视为不同,并且未找到&#34;方法&#34;。