在 ASP.NET Core 中,某些依赖项需要异步创建。例如,Playwright 可以这样初始化:
public static async Task Main(string[] args) {
var builder = WebApplication.CreateBuilder(args);
// ...
var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.LaunchAsync();
var browserContext = await browser.NewContextAsync();
services.AddSingleton(playwright);
services.AddSingleton(browser);
services.AddSingleton(browserContext);
// ...
await builder.Build().RunAsync();
}
这是可能的,因为
async Task Main()
。
但是当在单独的程序集或可重用库中执行时,通常使用以下模式:
builder.AddFoo();
其内部执行此操作:
webHostBuilder.ConfigureServices((context, services) => /* ... */);
...这不是异步的。
是否有异步方式在单独的库中注册服务?
为需要异步创建的服务注册一个工厂,然后在依赖类中需要时调用该工厂实例的
Create
方法。在创建单例的情况下,将工厂类注册为单例,然后在工厂内跟踪它创建的单例实例,并为所有对 Task<T>
的调用返回结果 Create
。简单的例子:
public PlaywriteFactory
{
public Lazy<Task<Playwrite>> _playwriteTask;
public PlaywriteFactory( ...depenencies... )
{
_playwriteTask = new Lazy<Task<Playwrite>>( () =>
{
... code that returns Task<Playwrite> ...
} );
}
public Task<Playwrite> CreateAsync()
{
return _playwriteTask.Value;
}
}
/////
services.AddSingleton<PlaywriteFactory>();
///// usage ///
public class SomeClass
{
private Task<Playwrite> _playwriteTask;
public SomeClass( PlaywriteFactory factory )
{
_playwriteTask = factory.CreateAsync();
}
public async Task SomeMethod()
{
var playwrite = await _playwriteTask;
...
}
}