3

我想做的是将两个演员(妈妈演员和爸爸演员)传递给儿童演员。由于使用演员参考而不是演员是最佳实践,因此我使用 IActorRef 为木乃伊演员和爸爸演员通过 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();
        }
    }
}
4

3 回答 3

4

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

我希望它会帮助你。

于 2015-09-22T11:41:55.900 回答
1

另一种解决方案是注入 Mummy 和 Daddy 的路径,并在 Kid 内部使用 Context.ActorSelection 在系统中找到它们。这更适合远程/集群情况,以及您有循环参考链的情况。

于 2016-02-08T05:22:35.267 回答
0

妈妈和爸爸演员是由每个儿童演员创建的。妈妈和爸爸演员要么需要唯一命名,要么注册为单身人士。

于 2015-09-01T20:47:52.047 回答