pbz*_*pbz 29 singleton dependency-injection asp.net-core
所以,假设我有一个单例类实例,我在DI中注册如下:
services.AddSingleton<IFoo, Foo>();
Run Code Online (Sandbox Code Playgroud)
并且假设Foo
该类具有许多其他依赖项(主要是允许其加载数据的存储库类).
根据我目前的理解,Foo实例在首次使用(询问)之前不会创建.有没有办法初始化除构造函数之外的这个类?就像ConfigureServices()
完成后一样?或者初始化代码(从db加载数据)是否应该在Foo的构造函数中完成?
(如果这个类在第一次使用之前加载其数据以加速第一次访问,那将是很好的)
Tse*_*eng 46
在启动期间自己动手.
var foo = new Foo();
services.AddSingleton<IFoo>(foo);
Run Code Online (Sandbox Code Playgroud)
或者"热身"
public void Configure(IApplicationBuilder app)
{
app.ApplicationServices.GetService<IFoo>();
}
Run Code Online (Sandbox Code Playgroud)
或者
public void Configure(IApplicationBuilder app, IFoo foo)
{
...
}
Run Code Online (Sandbox Code Playgroud)
但是如果你做了一些你不应该在构造函数中做的事情,那么这感觉很脏并且对你的设计来说更成问题.类实例化必须快速,如果你在其中进行长时间运行的操作,你就要打破一堆最佳实践,需要重构代码库,而不是寻找破解它的方法
最近,我一直将其创建为是否IHostedService
需要初始化,因为对我来说,让服务本身而不是在服务外部处理初始化似乎更合乎逻辑。
您甚至可以使用 aBackgroundService
代替,IHostedService
因为它非常相似,并且只需要实现ExecuteAsync
这是他们的文档
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services
如何添加服务以便可以直接注入它的示例:
services
.AddHostedService<MyService>()
.AddSingleton<MyService>(x => x
.GetServices<IHostedService>()
.OfType<MyService>()
.First());
Run Code Online (Sandbox Code Playgroud)
简单服务的示例:
public class MyService : IHostedService
{
// This function will be called automatically when the host `starts`
public async Task StartAsync(CancellationToken cancellationToken)
{
// Do initialization logic
}
// This function will be called automatically when the host `stops`
public Task StopAsync(CancellationToken cancellationToken)
{
// Do cleanup if needed
return Task.CompletedTask;
}
}
Run Code Online (Sandbox Code Playgroud)
我后来创建了一些扩展方法,因为我需要再次使用相同的模式
public static class HostedServiceExtensions
{
public static IServiceCollection AddHostedServiceAsService<T>(this IServiceCollection services) where T : class, IHostedService
=> services.AddHostedService<T>().AddSingleton(x => x.GetServices<IHostedService>().OfType<T>().First());
public static IServiceCollection AddHostedServiceAsService<T>(this IServiceCollection services, Func<IServiceProvider, T> factory) where T : class, IHostedService
=> services.AddHostedService(factory).AddSingleton(x => x.GetServices<IHostedService>().OfType<T>().First());
}
Run Code Online (Sandbox Code Playgroud)
使用就像
services.AddHostedServiceAsService<MyService>();
// Or like this if you need a factory
services.AddHostedServiceAsService<MyService>(x => new MyService());
Run Code Online (Sandbox Code Playgroud)
小智 7
我遇到了同样的问题,我找到 Andrew Lock 博客: https://andrewlock.net/running-async-tasks-on-app-startup-in-asp-net-core-3/
他解释了如何使用 asp .net core 3 执行此操作,但他还参考了有关如何使用早期版本执行此操作的页面。
添加详细信息到 J\xc3\xa9r\xc3\xb4me FLAMEN\ 的答案,因为它提供了我向单例调用异步初始化任务所需的密钥:
\n创建一个实现 IHostedService 的类:
\npublic class PostStartup : IHostedService\n{\n private readonly YourSingleton yourSingleton;\n\n public PostStartup(YourSingleton _yourSingleton)\n {\n yourSingleton = _yourSingleton;\n }\n\n // you may wish to make use of the cancellationToken\n public async Task StartAsync(CancellationToken cancellationToken)\n {\n await yourSingleton.Initialize();\n }\n\n // implement as you see fit\n public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;\n}\n
Run Code Online (Sandbox Code Playgroud)\n然后,在您的 中ConfigureServices
添加HostedService
引用:
services.AddHostedService<PostStartup>();\n
Run Code Online (Sandbox Code Playgroud)\n来自链接。
\n