Akka.NET 可以在 F# 系统中创建 C# actors 吗?
Akka.NET can C# actors be created within F# system?
我正在尝试使用 F# 系统中的 C# 库中定义的某些 ReceiveActor
。我尝试创建非 F# API ActorSystem
但对 system.ActorOf(Props.Create(fun () -> new CSharpActor()))
的调用不起作用,表示函数参数不兼容。
我在 F# API 页面中也找不到任何关于如何创建在 C# 库中定义的角色的文档。这只是没有完成吗?它通常是 "bad" 设计吗——也就是说,actor 系统应该在库本身中创建吗?
编辑:我在下面玩的代码
C#代码
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}"); });
}
}
}
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"
Props.Create
with function 将不起作用,因为 C# 中的 Props.Create(() => new Actor(a, b))
实际上是获取一个表达式,并将其解构为 actor 类型和构造函数参数。这是必要的,因为 Props 的要求之一是它必须是可序列化的。
你可以做的是使用 Props.Create(typeof<MyActor>, [| box myArg1; box myArg2 |])
的另一个重载,它基本上做同样的事情,只是没有编译类型安全。
话虽如此,如果可能的话,最好使用 Akkling or Akka.FSharp API。
我正在尝试使用 F# 系统中的 C# 库中定义的某些 ReceiveActor
。我尝试创建非 F# API ActorSystem
但对 system.ActorOf(Props.Create(fun () -> new CSharpActor()))
的调用不起作用,表示函数参数不兼容。
我在 F# API 页面中也找不到任何关于如何创建在 C# 库中定义的角色的文档。这只是没有完成吗?它通常是 "bad" 设计吗——也就是说,actor 系统应该在库本身中创建吗?
编辑:我在下面玩的代码
C#代码
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}"); });
}
}
}
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"
Props.Create
with function 将不起作用,因为 C# 中的 Props.Create(() => new Actor(a, b))
实际上是获取一个表达式,并将其解构为 actor 类型和构造函数参数。这是必要的,因为 Props 的要求之一是它必须是可序列化的。
你可以做的是使用 Props.Create(typeof<MyActor>, [| box myArg1; box myArg2 |])
的另一个重载,它基本上做同样的事情,只是没有编译类型安全。
话虽如此,如果可能的话,最好使用 Akkling or Akka.FSharp API。