2017-04-25 8 views
3

私はF#システム内のC#ライブラリで定義されたReceiveActorを使用しようとしています。私は非F#API ActorSystemを作成しようとしましたが、関数引数が互換性がないと言ってsystem.ActorOf(Props.Create(fun() -> new CSharpActor()))への呼び出しが機能しません。Akka.NETはF#システム内でC#アクタを作成できますか?

また、F#APIページでは、C#ライブラリで定義されたアクターを作成する方法に関するドキュメントも見つかりませんでした。これはちょうど行われていないですか?それは一般に「悪い」デザインですか?つまり、俳優システムを図書館自体の中に作成する必要がありますか?

EDIT:コード私はので、

以下のC#コード機能付きのF#スクリプト

#I @"../build" 

#r @"Akka.dll" 
#r @"Akka.FSharp.dll" 
#r @"CsActors.dll" 

open Akka.Actor 
open Akka.FSharp 
open CsActors 

let system = System.create "fcmixed" (Configuration.load()) 

// fails at runtime with "System.InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.InstanceMethodCallExpressionN' to type 'System.Linq.Expressions.NewExpression'." 
//let c1 = system.ActorOf(Props.Create(fun _ -> CsActor())) 

// works if CsActor has constructor with no arguments 
let c2 = system.ActorOf<CsActor> "c2" 
c2 <! "foo" 

// if actor doesn't have default constructor - this won't compile 
//let c3 = system.ActorOf<CsActorWithArgs> "c3" 

// Horusiath solution works for actors requiring arguments 
let c4 = system.ActorOf(Props.Create(typeof<CsActorWithArgs>, [| box "c4-prefix" |])) 
c4 <! "foo" 


// Just for fun trying to use suggestion by dumetrulo (couldn't quite get it to work...) 
// copied Lambda module from http://www.fssnip.net/ts/title/F-lambda-to-C-LINQ-Expression 
//module Lambda = 
// open Microsoft.FSharp.Linq.RuntimeHelpers 
// open System.Linq.Expressions 
// let toExpression (``f# lambda`` : Quotations.Expr<'a>) = 
//  ``f# lambda`` 
//  |> LeafExpressionConverter.QuotationToExpression 
//  |> unbox<Expression<'a>> 
//let c5 = system.ActorOf(Props.Create(<@ (fun _ -> CsActorWithArgs "c5-prefix") @> |> Lambda.toExpression)) 
//c5 <! "foo" 
+2

C#とF#はどちらもILにコンパイルされます。あなたが正しい型と引数などを提供する限り、他のF#ライブラリを呼び出すことと変わらないはずです。 – mason

+1

では、タイプシグネチャと正確なエラーメッセージを転記することができます。 – s952163

+2

おそらく、その関数をC# – Foole

答えて

2

Props.Createが動作しません

namespace CsActors { 
    using Akka.Actor; 
    using System; 

    public class CsActor : ReceiveActor { 
    public CsActor() { 
     Receive<string>(msg => { Console.WriteLine($"C# actor received: {msg}"); }); 
    } 
    } 

    public class CsActorWithArgs : ReceiveActor { 
    public CsActorWithArgs(string prefix) { 
     Receive<string>(msg => { Console.WriteLine($"{prefix}: {msg}"); }); 
    } 
    } 
} 

で遊んでいていること何ですか?C#での10は、実際に式を取り、それをアクターの型とコンストラクターの引数に分解しています。これは必要です。なぜなら、Propsの要件の1つは、シリアライズ可能でなければならないということです。

あなたができることは、コンパイルタイプの安全性を除いて、基本的に同じであるProps.Create(typeof<MyActor>, [| box myArg1; box myArg2 |])の別のオーバーロードを使用することです。

可能であれば、AkklingまたはAkka.FSharp APIを使用する方が良いと言われています。

関連する問題