gpt4 book ai didi

c# - 可以一遍又一遍地构建 ServiceProvider 吗?

转载 作者:行者123 更新时间:2023-12-04 00:58:44 26 4
gpt4 key购买 nike

在 .NET Core Console 应用程序中,我想使用内置的依赖注入(inject),包括自动处理链中的 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!");
}
}

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

Go!
Repository Disposed!
MyContext 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!

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

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!

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

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

最佳答案

创建一个作用域,从中解析所有依赖关系,然后释放该作用域。看起来像这样:

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();
}

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

关于c# - 可以一遍又一遍地构建 ServiceProvider 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60434776/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com