gpt4 book ai didi

c# - Akka.net DI - 如何通过 DI 注入(inject)两个 Actor ?

转载 作者:行者123 更新时间:2023-11-30 14:52:11 31 4
gpt4 key购买 nike

我想做的是将两个 Actor (木乃伊 Actor 和爸爸 Actor )传递给小 Actor 。由于使用 actor 引用而不是 actor 是最佳实践,因此我使用 IActorRef 将木乃伊 actor 和爸爸 actor 使用命名参数通过 DI 注入(inject)。但我收到“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();

我使用参数名称进行检查。但是我认为这个解决方案可能非常危险,尤其是如果您重命名参数。

您可以做的另一件事是将这些实例的创建委托(delegate)给具有特定方法的服务/工厂,并且该服务通过 DI 注入(inject)。

这是经过一些重构后我得到的:

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();
}
}

希望对您有所帮助。

关于c# - Akka.net DI - 如何通过 DI 注入(inject)两个 Actor ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32303894/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com