[英]Akka.net DI - How to inject two actors thru DI?
我想要做的是將兩個演員(木乃伊演員和爸爸演員)傳給小伙子演員。 因為這是使用actor引用而不是actor的最佳實踐,我使用IActorRef為mummy actor和daddy actor通過DI注入命名參數。 但我得到“mummyActor不是唯一的”錯誤。 知道怎么解決嗎?
using System;
using System.Threading.Tasks;
using Akka.Actor;
using Akka.DI.AutoFac;
using Akka.DI.Core;
using Autofac;
using Autofac.Core;
namespace Akka.DI.AutoFac.ExampleConsole {
public class DaddyActor : ReceiveActor {
public DaddyActor() {
Receive<DoneEatingMessage>(m => {
Console.WriteLine("Kid finished eating. So what? ~ Dad");
});
}
}
public class MummyActor : ReceiveActor {
public MummyActor() {
Receive<DoneEatingMessage>(m => {
Console.WriteLine("Kid finished eating. Time to clean up! ~Mummy");
});
}
}
public class KidActor : ReceiveActor {
private IService _service;
private IActorRef _mummyActor;
private IActorRef _daddyActor;
public KidActor(IService service, IActorRef mummyActor, IActorRef daddyActor) {
this._service = service;
this._mummyActor = mummyActor;
this._daddyActor = daddyActor;
Receive<EatMessage>(m=>{
var food = service.GetFood();
Console.WriteLine("Kid eat this food {0}", food);
_mummyActor.Tell(new DoneEatingMessage());
});
}
}
public class EatMessage{ }
public class DoneEatingMessage { }
public interface IService {
string GetFood();
}
public class FoodService : IService {
public string GetFood() {
return "banana";
}
}
class Program {
static ActorSystem _actorSystem;
static void Main(string[] args) {
var builder = new Autofac.ContainerBuilder();
builder.RegisterType<FoodService>().As<IService>();
builder.RegisterType<MummyActor>().InstancePerDependency();
builder.RegisterType<DaddyActor>().InstancePerDependency();
builder.Register(c => _actorSystem.ActorOf(_actorSystem.DI().Props<DaddyActor>(), "daddyActor"))
.Named<IActorRef>("daddyActorRef")
.AsSelf();
builder.Register(c => _actorSystem.ActorOf(_actorSystem.DI().Props<MummyActor>(), "mummyActor"))
.Named<IActorRef>("mummyActorRef")
.AsSelf();
builder.RegisterType<KidActor>()
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(MummyActor),
(pi, ctx) => ctx.ResolveNamed<IActorRef>("mummyActorRef")
)
)
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(DaddyActor),
(pi, ctx) => ctx.ResolveNamed<IActorRef>("daddyActorRef")
)
)
.InstancePerDependency();
var container = builder.Build();
_actorSystem = ActorSystem.Create("ActorDISystem");
var propsResolver = new AutoFacDependencyResolver(container, _actorSystem);
var kidActorProps = _actorSystem.DI().Props<KidActor>();
var kidActor = _actorSystem.ActorOf(kidActorProps, "kidActor");
kidActor.Tell(new EatMessage());
Console.WriteLine("Holah");
Console.ReadLine();
}
}
}
問題是MummyActor和DaddyActor類型不是IActorRef的實例。 所以在創建KidActor時不能使用這些類型。
我對AutoFac不是很熟悉,但我能夠讓它像這樣工作:
builder.RegisterType<KidActor>()
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.Name == "mummyActor",
(pi, ctx) => ctx.ResolveNamed<IActorRef>("mummyActorRef")
)
)
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.Name == "daddyActor",
(pi, ctx) => ctx.ResolveNamed<IActorRef>("daddyActorRef")
)
)
.InstancePerDependency();
我使用參數的名稱進行檢查。 但我認為這種解決方案非常危險,尤其是重命名參數時。
您可以做的另一件事是將這些實例的創建委托給具有特定方法的服務/工廠,並通過DI注入此服務。
這是我在進行一些重構之后得到的:
public class DaddyActor : ReceiveActor
{
public DaddyActor()
{
Receive<DoneEatingMessage>(m =>
{
Console.WriteLine("Kid finished eating. So what? ~ Dad");
});
}
}
public class MummyActor : ReceiveActor
{
public MummyActor()
{
Receive<DoneEatingMessage>(m =>
{
Console.WriteLine("Kid finished eating. Time to clean up! ~Mummy");
});
}
}
public class KidActor : ReceiveActor
{
private IService _service;
private IActorRef _mummyActor;
private IActorRef _daddyActor;
public KidActor(IService service, IParentFactory parentFactory)
{
this._service = service;
this._mummyActor = parentFactory.CreateMother(Context.System);
this._daddyActor = parentFactory.CreateFather(Context.System);
Receive<EatMessage>(m =>
{
var food = service.GetFood();
Console.WriteLine("Kid eat this food {0}", food);
_mummyActor.Tell(new DoneEatingMessage());
_daddyActor.Tell(new DoneEatingMessage());
});
}
}
public class EatMessage { }
public class DoneEatingMessage { }
public interface IService
{
string GetFood();
}
public class FoodService : IService
{
public string GetFood()
{
return "banana";
}
}
public interface IParentFactory
{
IActorRef CreateMother(ActorSystem actorSystem);
IActorRef CreateFather(ActorSystem actorSystem);
}
public class ParentFactory : IParentFactory
{
public IActorRef CreateFather(ActorSystem actorSystem)
{
return actorSystem.ActorOf(actorSystem.DI().Props<DaddyActor>(), "daddyActor");
}
public IActorRef CreateMother(ActorSystem actorSystem)
{
return actorSystem.ActorOf(actorSystem.DI().Props<MummyActor>(), "mummyActor");
}
}
class Program
{
static ActorSystem _actorSystem;
static void Main(string[] args)
{
var builder = new Autofac.ContainerBuilder();
builder.RegisterType<FoodService>().As<IService>();
builder.RegisterType<ParentFactory>().As<IParentFactory>();
builder.RegisterType<MummyActor>().InstancePerDependency();
builder.RegisterType<DaddyActor>().InstancePerDependency();
builder.RegisterType<KidActor>().InstancePerDependency();
var container = builder.Build();
_actorSystem = ActorSystem.Create("ActorDISystem");
var propsResolver = new AutoFacDependencyResolver(container, _actorSystem);
var kidActorProps = _actorSystem.DI().Props<KidActor>();
var kidActor = _actorSystem.ActorOf(kidActorProps, "kidActor");
kidActor.Tell(new EatMessage());
Console.WriteLine("Holah");
Console.ReadLine();
_actorSystem.AwaitTermination();
}
}
我希望它會對你有所幫助。
另一種解決方案是注入Mummy和Daddy的路徑,並使用Kid內部的Context.ActorSelection在系統中查找它們。 這適用於遠程/群集情況,以及您有周期性參考鏈的情況。
每個小孩演員都在制作木乃伊和爸爸演員。 木乃伊和爸爸演員要么必須具有獨特的名稱,要么注冊為單身人士。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.