Service Fabric and Dependency Injection, part 1: Stateful Service

This is a series of blog posts:

The template of a Service Fabric application that is shipped with Visual Studio instantiates all services explicitly. Like and any other basic template, such as of ASP.NET infrastructure pipeline, it instantiates all filters and handlers right away as well.

But sooner or later you’ll likely have to pass to your service some dependencies, which have their own dependencies, and so on. This way you end up having a dependency tree. Natural answer to its growing complexity would be using a Dependency Injection (DI) container. I cannot recommend more Simple Injector for its performance and elegance of API.

Another reason to use a container would be the design principle which suggests that all constructor calls in your code (the new keyword in C-like languages) are the aspects of explicit lifetime (aka lifestyle) management scattered across your codebase. While actually it has to be performed by a container in one, centralized place called composition root.

ServiceRuntime.RegisterServiceAsync(nameof(MyStatefulService) + "Type", context => CreateService(context))
              .GetAwaiter()
              .GetResult();
 
private static StatefulServiceBase CreateService(StatefulServiceContext context)
{
    var container = ContainerConfig.CreateContainer(context);
    return container.GetInstance();
}

Now you only need to register the service (optionally) and the service context (mandatory):

internal static class ContainerConfig
{
    public static Container CreateContainer(StatefulServiceContext context)
    {
        var container = new Container();
        container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
 
        container.RegisterInstance<StatefulServiceContext>(context);
        container.RegisterInstance<ServiceContext>(context);
        container.RegisterSingleton<MyStatefulService>();
 
        return container;
    }
}

The caveat here is to map service context to two types, StatefulServiceContext and ServiceContext. Why? Because you’ll likely have both steteful and stateless services in your application, and their dependencies, such as configuration management, will likely depend on the base type ServiceContext. Meanwhile services require the concrete type in their respective constructors. The good thing is that the same instance would be resolved in both cases:

public sealed class MyStatefulService
{
    public MyStatefulService(StatefulServiceContext context, ...)
    {
    }
}
 
public sealed class ServiceFabricConfigurationManager : IConfigurationManager
{
    public ServiceFabricConfigurationManager(ServiceContext context, ...)
    {
    }
}

That’s it! Now your stateful service itself and all its dependencies are recursively instantiated and controlled by the container.

This entry was posted in Programming and tagged , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.