Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Akka.NET DI on Windows Services & Best Practices

I am trying to migrate parts of a Windows Service into the AKKA.net actor model however when it comes to DI for the actors (they have some dependencies such as data access layer, etc.) I'm having a bit of a problem because I don't fully understand how to wire up the DependencyResolver in the service. If that was a web application then it would be DependencyResolver of the HttpConfiguraiton however in this case I currently have the standard kernel to do the bootstrapping and get the top level interface implementacion to start the Windows Service.

I would have then two questions:

  • What's the way to configure DI for actors in windows services?
  • What's the best way to get the system actor from within another class?

I have been reading here: http://getakka.net/docs/Dependency%20injection#ninject

Thanks in advance!

like image 286
Carlos Torrecillas Avatar asked Nov 23 '25 08:11

Carlos Torrecillas


1 Answers

I'm using Akka.NET in a windows service (with topshelf and autofac but this approach should work for any service runner and IoC framework). I start up the top level actor in the startup method of the service like so:

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

From there I create child actors with either

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

where the actor type has a default constructor, or

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

where the child actor type has dependencies.

The ActorOfDI calls are extension methods which I use to wrap the ActorSystem.DI() and IActorContext.DI() methods in akka.net as follows:

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

In terms of IoC configuration for the actors, I'm registering all actor types in the assemblies containing the actors (using Autofac) as follows:

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

and to register the actor system itself I'm doing this:

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

where lazyContainer is a:

Lazy<IContainer> // this is an autofac type

and the constructor delegate calls

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

To get the actor system from within another dependency injected class you can then just pass an ActorSystem into the constructor for the class. I'm not sure about getting a reference to the system actor in my application code - I haven't needed to do that myself.

like image 138
Steve Willcock Avatar answered Nov 24 '25 21:11

Steve Willcock



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!