首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用F#库中的Akka.Net参与者调用C#库将导致TypeInitializationException

使用F#库中的Akka.Net参与者调用C#库将导致TypeInitializationException
EN

Stack Overflow用户
提问于 2016-04-06 16:47:36
回答 1查看 367关注 0票数 3

在我的测试解决方案中有3个项目:

  • f#类库(让我们命名为F#Lib),
  • f#控制台应用程序(让我们命名它为F#Console)和
  • c#控制台应用程序(C#Console)。

在类库中,我定义了一个akka.net参与者:

代码语言:javascript
复制
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

如果我从MainClass控制台应用程序实例化f#,就会得到预期的结果:

代码语言:javascript
复制
[<EntryPoint>]
let main argv = 
    Just.Test.Project.MainClass("bugaga!") |> ignore
    System.Threading.Thread.Sleep(1000)
    0 // return an integer exit code

产出:

代码语言:javascript
复制
"bugaga!!!"

但。如果我在c#控制台应用程序中也这样做的话:

代码语言:javascript
复制
static void Main(string[] args)
{
    new Just.Test.Project.MainClass("bugaga!");
    System.Threading.Thread.Sleep(1000);
}

我有个例外:

代码语言:javascript
复制
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的答复中已经指出的那样,这个问题与版本不匹配有关。bindingRedirect完成了工作,一切都开始工作了。但我还是有一些误会。

第一。Akka.FSharp引用FSharp.Core 4.3.1

第二。F#Lib和F#Console引用FSharp.Core 4.4.0和C#Console根本没有对FSharp.Core的引用。

第三。F#Console工作起来很有魅力,如果我打印加载的程序集,就会得到:

代码语言:javascript
复制
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加载,一切都是顶顶!

第四。C#Console不起作用。加载的程序集列表看起来有点奇怪:

代码语言:javascript
复制
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.0FSharp.Core, Version=4.3.1.0都已加载。为什么?为什么在F#Console案件中没有发生这种情况?

溶液

这个问题(和往常一样)在我的脑海里。

首先,我从未研究过最终的F#Console配置。初始的app.config非常简单:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
</configuration>

但是在构建完成之后(多亏了AutoGenerateBindingRedirects MSBuild标志,所需的buinding重定向:

代码语言:javascript
复制
  <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#编译器试图通过在构建输出中写入这样的消息来通知我这个问题:

无法解决"FSharp.Core,Version=4.3.1.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a“和"FSharp.Core,Version=4.3.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a”之间的冲突。任意选择"FSharp.Core,Version=4.3.1.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a“。考虑从版本"4.3.1.0“C:\Program (x86)\Reference Assemblies\Microsoft\FSharp.NETFramework\v4.0\4.3.1.0\FSharp.Core.dll到版本"4.4.0.0”C:\Program (x86)\Reference Assemblies\Microsoft\FSharp.NETFramework\v4.0\4.4.0.0\FSharp.Core.dll对程序集"FSharp.Core,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a“的app.config重新映射,以解决冲突并消除警告。C:\Program (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(1820,5):警告MSB3276:发现同一依赖程序集的不同版本之间的冲突。请在项目文件中将"AutoGenerateBindingRedirects“属性设置为true。有关更多信息,请参见http://go.microsoft.com/fwlink/?LinkId=294190

但我认为C#编译器只是像F#编译器那样限制了一点。我不知道在F#项目中,标志是自动设置的。是什么阻止我检查的?我不知道!)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-04-06 20:34:19

这听起来像是FSharp.Core.dll版本不匹配的问题。

最有可能的情况是,您引用的FSharp.Core.dll版本比F#包装库为Akka.net引用的版本更新。您可以引用相同的版本,也可以使用bindingRedirect添加配置文件。见马克·塞曼的博客文章

这里的关键字是MethodMissingException,因为方法的签名涉及来自FSharp.Core.dll的类型,并且已经加载的版本(基于C#项目中的引用)与包装器公开的版本不匹配(基于编译包装器时使用的引用)。由于版本不匹配,这些类型被视为不同的类型,并且“找不到方法”。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36457396

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档