3

Good afternoon,

I recently started experimenting with Service Fabric and .NET Core. I created a Stateless Web API and performed some DI using:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    var connString = Configuration.GetConnectionString("DefaultConnection");
    services.AddScoped<FaxLogic>();
    services.AddDbContext<ApplicationContext>(options => options.UseSqlServer(connString));
}

With the above I can use constructor inject on my FaxLogic class as well as my DbContext class (through the FaxLogic):

private readonly FaxLogic _faxLogic;
public FaxController(
    FaxLogic faxLogic)
{
    _faxLogic = faxLogic;
}
private readonly ApplicationContext _context;
public FaxLogic(ApplicationContext context)
{
    _context = context;
}

I then created a non-Web API stateless service. I want to be able to access my FaxLogic and DbContext like in my WebAPI, but within the RunAsync method of the stateless service:

protected override async Task RunAsync(CancellationToken cancellationToken)
{
    // TODO: Replace the following sample code with your own logic 
    //       or remove this RunAsync override if it's not needed in your service.

    while (true)
    {
        cancellationToken.ThrowIfCancellationRequested();

        ServiceEventSource.Current.ServiceMessage(this.Context, "Hello!");

        // do db stuff here!

        await Task.Delay(TimeSpan.FromSeconds(5), cancellationToken);
    }
}

I am wondering how I'd do it. I tried playing with the CreateServiceInstanceListeners() method and the Program.cs file where ServiceRuntime is is used to register but I can't seem to figure it out! Any help would be appreciated.

Pac0
  • 21,465
  • 8
  • 65
  • 74
Ha.TaeSeo
  • 35
  • 3
  • https://www.jamessturtevant.com/posts/Dependency-Injection-with-Azure-Service-Fabric/ – mukesh joshi Feb 15 '19 at 05:24
  • Possible duplicate of [Set up Dependency Injection on Service Fabric using default ASP.NET Core DI container](https://stackoverflow.com/questions/54185571/set-up-dependency-injection-on-service-fabric-using-default-asp-net-core-di-cont) – Stephen Kennedy Apr 30 '19 at 19:28

2 Answers2

1

The solution has been already answered here: Set up Dependency Injection on Service Fabric using default ASP.NET Core DI container

In summary, you have to register the dependencies before you create a new instance of your stateless service and then create a factory method to resolve the dependencies:

i.e:

public static class Program
{
    public static void Main(string[] args)
    {
        var provider = new ServiceCollection()
                    .AddLogging()
                    .AddSingleton<IFooService, FooService>()
                    .AddSingleton<IMonitor, MyMonitor>()
                    .BuildServiceProvider();

        ServiceRuntime.RegisterServiceAsync("MyServiceType",
            context => new MyService(context, provider.GetService<IMonitor>());
        }).GetAwaiter().GetResult();

See the linked answer for more details.

Diego Mendes
  • 10,631
  • 2
  • 32
  • 36
  • Hello Diego! Thank you for the answer! In the Startup.cs file for the API, I have access to the IConfiguration interface to get a connection string from a loaded AppSettings.json. How would I go about doing something similar for the DbContext in Program.cs if I want to .AddDbContext? – Ha.TaeSeo Feb 18 '19 at 13:03
  • Ah nevermind, I have resolved the issue. My apologies I was not looking hard enough, and was a little confused. Thanks for all your help! – Ha.TaeSeo Feb 18 '19 at 14:16
  • @Diego Mendes I am a bit confused with your answer. Shouldn't the provider register all DI and then pass that to the Service class? In your snippet, why are you passing provider.GetService instead of just process. What happens to IFooService in this case? – Lee Z Jun 10 '20 at 19:01
  • This is just an example, you will pass whatever dependency your service need. If you want you can pass the provider to the service and the service resolve it's own dependencies. The linked answer has mode information. – Diego Mendes Jun 11 '20 at 20:39
  • In this approach, who is responsible for disposing the ServiceProvider instance (and all underlying objects registered as dependencies)? – mcs_dodo Sep 12 '22 at 14:09
0

TaeSeo,

I think what you are looking for is implemented in the project I am working on - CoherentSolutions.Extensions.Hosting.ServiceFabric.

In the terms of CoherentSolutions.Extensions.Hosting.ServiceFabric what you are looking for would look like:

private static void Main(string[] args)
{
  new HostBuilder()
    .DefineStatelessService(
      serviceBuilder => {
        serviceBuilder
          .UseServiceType("ServiceName")
          .DefineDelegate(
            delegateBuilder => {
              delegateBuilder.ConfigureDependencies(
                dependencies => {
                  dependencies.AddScoped<FaxLogic>();
                });
              delegateBuilder.UseDelegate(
                async (StatelessServiceContext context, FaxLogic faxLogic) => {
                  while (true) {
                    cancellationToken.ThrowIfCancellationRequested();

                    ServiceEventSource.Current.ServiceMessage(context, "Hello!");

                    await Task.Delay(TimeSpan.FromSeconds(5), cancellationToken);
                });
            })
       })
    .Build()
    .Run();
}

If you have more questions feel free to ask or check out the project wiki

Hope it helps.

Oleg Karasik
  • 959
  • 6
  • 17
  • 1
    Oleg, thank you for your response, but Diego has solved this issue for me. I will still take a look at your project though, it looks very useful and interesting! – Ha.TaeSeo Feb 18 '19 at 14:17