Akka.NET DI по службам Windows и рекомендациям

Я пытаюсь перенести части службы Windows в модель актера AKKA.net, однако, когда дело доходит до DI для актеров (у них есть некоторые зависимости, такие как уровень доступа к данным и т. д.), у меня возникла небольшая проблема, потому что Я не совсем понимаю, как подключить DependencyResolver в службе. Если бы это было веб-приложение, то это был бы DependencyResolver HttpConfiguraiton, однако в этом случае у меня в настоящее время есть стандартное ядро ​​для начальной загрузки и реализации интерфейса верхнего уровня для запуска службы Windows.

У меня тогда возникло бы два вопроса:

  • Как настроить DI для субъектов в службах Windows?
  • Каков наилучший способ получить системного актера из другого класса?

Я читал здесь: http://getakka.net/docs/Dependency%20injection#ninject

Заранее спасибо!


person Carlos Torrecillas    schedule 04.02.2016    source источник


Ответы (2)


Я использую Akka.NET в службе Windows (с верхней полкой и автофаком, но этот подход должен работать для любого исполнителя службы и инфраструктуры IoC). Я запускаю актера верхнего уровня в методе запуска службы следующим образом:

_scope.Resolve<ActorSystem>().ActorOf<MyTopLevelActor>().Tell(new StartMySystemMessage());

Оттуда я создаю дочерних актеров с помощью

var actorWithoutDependencies = Context.ActorOf<ChildActorType>();

где тип актора имеет конструктор по умолчанию, или

var actorWithDependencies = Context.ActorOfDI<ChildActorType>();

где тип дочернего актора имеет зависимости.

Вызовы ActorOfDI — это методы расширения, которые я использую для переноса методов ActorSystem.DI() и IActorContext.DI() в akka.net следующим образом:

    public static IActorRef ActorOfDI<T>(this ActorSystem actorSystem, string name = null) where T : ActorBase
    {
        return actorSystem.ActorOf(actorSystem.DI().Props<T>(), name);
    }

    public static IActorRef ActorOfDI<T>(this IActorContext actorContext, string name = null) where T : ActorBase
    {
        return actorContext.ActorOf(actorContext.DI().Props<T>(), name);
    }

Что касается конфигурации IoC для акторов, я регистрирую все типы акторов в сборках, содержащих акторы (используя Autofac), следующим образом:

containerBuilder.RegisterAssemblyTypes(typeof(SomeActorType).Assembly).Where(x => x.Name.EndsWith("Actor"));

а для регистрации самой системы акторов делаю так:

containerBuilder.Register(c =>
{
    var system = ActorSystem.Create("MyActorSystem");
    // ReSharper disable once ObjectCreationAsStatement
    new AutoFacDependencyResolver(lazyContainer.Value, system);
    return system;
}).As<ActorSystem>().SingleInstance();

где lazyContainer - это:

Lazy<IContainer> // this is an autofac type

и делегат конструктора вызывает

containerBuilder.Build() // this is an autofac call

Чтобы получить акторную систему из другого класса с внедренной зависимостью, вы можете просто передать ActorSystem в конструктор класса. Я не уверен в получении ссылки на системного актера в коде моего приложения — мне не нужно было делать это самому.

person Steve Willcock    schedule 04.02.2016
comment
Привет, Стив, большое спасибо за это. Я получил это, используя ваши советы и методы расширения. В данный момент я использую Ninject, но решение очень похожее. Мой вариант использования, однако, состоял бы в том, чтобы иметь зависимость от системного актера (IActorRefFactory), которую я внедряю в свой первый класс, не являющийся актером, который будет его использовать. Затем оттуда мне нужно получить актера верхнего уровня, которого я передам, и получу первого актера, и передам свое стартовое сообщение. Из этого актера я могу получить доступ к контексту и разрешить DIActors, используя ваш метод расширения. Имеет ли это смысл? Большое спасибо! - person Carlos Torrecillas; 05.02.2016
comment
Привет, Карлос, отлично, я рад, что помог. Да, ваш сценарий имеет смысл для меня - я ввожу конкретную систему ActorSystem на верхнем уровне, поскольку это немного упрощает мой сценарий, но внедрение IActorRefFactory тоже может работать. - person Steve Willcock; 05.02.2016

Я бы настроил свой DI сразу после запуска системы акторов для процесса. Это лучшее, что я могу предложить, поскольку я еще не использовал Akka в контексте службы Windows.

Если вам нужны другие классы для доступа к системе акторов, чтобы иметь возможность создавать акторы верхнего уровня, вы можете зарегистрировать сам экземпляр системы акторов как IActorRefFactory, что дает вам доступ к методам ActorOf() и ActorSelection(). Очевидно, что здесь единичный экземпляр, а не преходящая продолжительность жизни.

Если вы имеете в виду, что хотите разрешить системный актор, а не акторсистему, то есть /system актор в других классах, я не уверен, что это возможно. Мое ограниченное понимание DI в Akka.net заключается в том, что вы не можете регистрировать и разрешать живых акторов, поскольку это не работает в отношении жизненных циклов акторов, вы можете только регистрировать зависимости, необходимые для запуска новых акторов. В результате я обычно запускаю своих акторов верхнего уровня вручную примерно в то время, когда я регистрирую свой контейнер и всех их дочерних элементов через DI.

Если у вас есть изолированные классы, которые не являются акторами и которым нужна точка доступа в акторную систему, я предлагаю зарегистрировать IActorRefFactory, как указано выше, и создать этих акторов по мере необходимости.

Это что-то вроде проблемы с квадратным стержнем и круглым отверстием, с которой я столкнулся в своем собственном проекте, поэтому я буду рад любым другим ответам, которые предлагают лучший способ.

person Patrick Allwood    schedule 04.02.2016