I have spent some months writing code with ASP.NET Core MVC. Now I am having a go at worker services but came across some issues with Dependency Injection.
I can register a service in Program.cs and use it in Worker.cs (see below). My problem comes up when you need the service deep down in the class structures like this:
- create object 1 in Worker.cs
- object 1 has object 2 as property
- object 2 needs the service for instantiation
- object 1 has object 2 as property
Of course, I could pass the service down the whole hierarchy but in this case, I do not see the value of services. It seems like I can use Dependency Injection only on the level of the worker service. In MVC you can simply register a service and pass it to a Controller’s constructor as an argument. The advantage here was that you never had to call the constructor explicitly just like one the level of Worker.cs. I came about this problem while trying to access connection strings and settings but I guess the same applies to the logger.
Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
services.AddTransient<ITestService,TestService>();
});
Worker.cs
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
public readonly ITestService TestServ;
public Worker(ILogger<Worker> logger, ITestService test)
{
_logger = logger;
TestServ = test;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
//this works
_logger.LogInformation("TestService: " + TestServ.GetData());
//is this necessary?
TestClassServ test = new TestClassServ(TestServ);
_logger.LogInformation("TestService: " + test.GetData());
await Task.Delay(1000, stoppingToken);
}
}
}
Class and Service
public interface ITestService
{
string GetData();
}
public class TestService : ITestService
{
public const string teststring = "service";
public string GetData()
{
return teststring;
}
}
public class TestClassServ
{
public ITestService TestServ { get; set; }
public TestClassServ(ITestService testServ)
{
TestServ = testServ;
}
public string GetData()
{
return TestServ.GetData();
}
}
After weeks of googling and trying, I have decided to ask you for help:
- Is it even possible to inject a service on a lower level of class hierarchies without passing it down from the top?
- How would you do that?
- Is my problem rooted in the architecture of the program?