Search code examples
c#azureazure-service-fabric

How to get the ServiceContext of a Reliable Service in Service Fabric?


The ServiceContext of a reliable service in Service Fabric is registered with the runtime (DI container) in the program.cs of the service:

ServiceRuntime.RegisterServiceAsync("RelDictQuerySvcType",
                    context => new RelDictQuerySvc(context)).GetAwaiter().GetResult();

How can I get that ServiceContext back from the DI container? There is no property on the ServiceRuntime to get it back. Also, I did not find it via the FabricClient. Do I need to put the context on an own static class in the service constructor to be able to get a reference to it somewhere else in my code?


Solution

  • Service Fabric does not really has a build-in DI mechanism, at least it is a very simple one.

    If you want to inject dependencies into you services itself you can use a factory. for example:

    ServiceRuntime.RegisterServiceAsync("MyStatelessType",
                    context =>
                    {
                        var loggerFactory = new LoggerFactoryBuilder(context).CreateLoggerFactory(applicationInsightsKey);
                        ILogger logger = loggerFactory.CreateLogger<MyStateless>();
    
                        return new MyStateless(context, logger);
                    }).GetAwaiter().GetResult();
    

    this is a way to inject concrete implementations in your service. This mechanism is used to inject the context as well. Unfortunately, since it is not a full fledged DI container you cannot get this context outside the service instance itself.

    So, you have to bring your own DI container to really use it, for example in a stateless web api you can do something like:

        protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
        {
            return new[]
            {
                new ServiceInstanceListener(serviceContext =>
                    new WebListenerCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
                    {
                        logger.LogStatelessServiceStartedListening<WebApi>(url);
    
                        return new WebHostBuilder().UseWebListener()
                                    .ConfigureServices(
                                        services => services
                                            .AddSingleton(serviceContext)
                                            .AddSingleton(logger)
                                            .AddTransient<IServiceRemoting, ServiceRemoting>())
                                    .UseContentRoot(Directory.GetCurrentDirectory())
                                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                                    .UseStartup<Startup>()
                                    .UseUrls(url)
                                    .Build();
                    }))
            };
        }
    

    Otherwise you have to do it yourself. There are some initiatives already, see this one for an AutoFac extensions and there is also a Unity extensions.