In a .NET Core Console application, I want to use the built-in dependency injection, including the automatic disposal of IDisposable objects in the chain. In ASP.NET Core, the objects are created and disposed with each request, which seems reasonable.
But in a Console app, I have to build the service provider, then start it by retrieving the first item in the chain from the provider and running:
class Program {
static void Main() {
using var serviceProvider = new ServiceCollection()
.AddTransient<Program>()
.AddTransient<Repository>()
.AddTransient<MyContext>()
.BuildServiceProvider();
serviceProvider.GetService<Program>().Go();
}
private readonly Repository _repo;
public Program(Repository repo) => _repo = repo;
public void Go() => _repo.Go();
}
public class Repository : IDisposable {
private readonly MyContext _context;
public Repository(MyContext context) => _context = context;
public void Go() => Console.WriteLine("Go!");
public void Dispose() => Console.WriteLine("Repository Disposed!");
}
public class MyContext : DbContext {
public override void Dispose() {
base.Dispose();
Console.WriteLine("MyContext Disposed!");
}
}
When the serviceProvider is disposed, the rest get disposed as well:
Go!
Repository Disposed!
MyContext Disposed!
If I want to run the process in a loop or with a timer, nothing gets disposed until the service provider itself is disposed:
for (int i = 0; i < 3; ++i)
{
serviceProvider.GetService<Program>().Go();
}
Go!
Go!
Go!
Repository Disposed!
MyContext Disposed!
Repository Disposed!
MyContext Disposed!
Repository Disposed!
MyContext Disposed!
If I dispose and recreate the service provider every time, I get the results I want:
for (int i = 0; i < 3; ++i)
{
using var serviceProvider = new ServiceCollection()
.AddTransient<Program>()
.AddTransient<Repository>()
.AddTransient<MyContext>()
.BuildServiceProvider();
serviceProvider.GetService<Program>().Go();
}
Go!
Repository Disposed!
MyContext Disposed!
Go!
Repository Disposed!
MyContext Disposed!
Go!
Repository Disposed!
MyContext Disposed!
My question: Is it ok to keep building and disposing the provider over and over again like this? I'm thinking of doing this on a timer every few seconds indefinitely. Is it an expensive process to do this, and is there a better way, without having to manually dispose the objects throughout the chain?
Or is this maybe what ASP.NET Core is doing behind the scenes anyway, recreating the provider with every request?