可以一遍又一遍地构建 ServiceProviders 吗?

Joe*_*nos 3 c# dependency-injection .net-core

在 .NET Core Console 应用程序中,我想使用内置的依赖注入,包括IDisposable链中对象的自动处理。在 ASP.NET Core 中,每个请求都会创建和处理对象,这似乎是合理的。

但是在控制台应用程序中,我必须构建服务提供者,然后通过从提供者检索链中的第一项并运行来启动它:

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!");
    }
}
Run Code Online (Sandbox Code Playgroud)

serviceProvider被处置时,其余的也会被处置:

Go!
Repository Disposed!
MyContext Disposed!
Run Code Online (Sandbox Code Playgroud)

如果我想在循环中或使用计时器运行该过程,则在处理服务提供者本身之前,不会处理任何内容:

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!
Run Code Online (Sandbox Code Playgroud)

如果我每次都处理并重新创建服务提供者,我会得到我想要的结果:

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!
Run Code Online (Sandbox Code Playgroud)

我的问题:像这样一遍又一遍地构建和处理提供程序可以吗?我正在考虑每隔几秒钟无限期地在计时器上执行此操作。这样做是否是一个昂贵的过程,有没有更好的方法,而不必手动处理整个链中的对象?

或者这可能是 ASP.NET Core 在幕后所做的事情,为每个请求重新创建提供程序?

Kir*_*kin 6

创建一个范围,从中解决所有依赖项,然后处置该范围。看起来像这样:

using var serviceProvider = new ServiceCollection()
    .AddTransient<Program>()
    .AddTransient<Repository>()
    .AddTransient<MyContext>()
    .BuildServiceProvider();

for (int i = 0; i < 3; ++i)
{
    using var scope = serviceProvider.CreateScope();
    scope.ServiceProvider.GetService<Program>().Go();
}
Run Code Online (Sandbox Code Playgroud)

当服务范围本身被释放时,由服务范围创建的所有范围和瞬态服务都会被释放。在这个例子中,所有涉及的服务都注册为瞬态,这意味着每次Program请求时都会创建新实例。如果您Program要从同一服务范围多次请求,您将获得所有必需注册服务的多个实例。这些实例中的每一个都由服务范围跟踪并与服务范围一起处理。