简体   繁体   English

ASP.NET 配置DI后核心初始化singleton

[英]ASP.NET Core initialize singleton after configuring DI

So let's say I have a singleton class instance that I register in the DI like this:所以假设我有一个 singleton class 实例,我像这样在 DI 中注册:

services.AddSingleton<IFoo, Foo>();

And let's say the Foo class has a number of other dependencies (mostly repository classes that allow it to load data).假设Foo class 有许多其他依赖项(主要是允许它加载数据的存储库类)。

With my current understanding, the Foo instance is not created until it's first used (asked).根据我目前的理解, Foo 实例在第一次使用(询问)之前不会被创建。 Is there a way to initialize this class other than the constructor?除了构造函数之外,还有其他方法可以初始化这个 class 吗? Like right after ConfigureServices() completes?就像ConfigureServices()完成后一样? Or should the initialization code (loading data from db) be done in Foo's constructor?还是应该在 Foo 的构造函数中完成初始化代码(从数据库加载数据)?

(It would be nice if this class could load its data before the first use to speed up first time access) (如果这个class可以在第一次使用之前加载它的数据以加快第一次访问,那就太好了)

Do it yourself during startup.在启动时自己做。

var foo = new Foo();
services.AddSingleton<IFoo>(foo);

Or "warm it up"或者“热身”

public void Configure(IApplicationBuilder app) 
{
    app.ApplicationServices.GetService<IFoo>();
}

or alternatively或者

public void Configure(IApplicationBuilder app, IFoo foo) 
{
    ...
}

But this feels just dirty and is more a problem with your design, if you do something that you shouldn't in the constructor.但是如果你在构造函数中做了一些你不应该做的事情,这感觉很脏,而且更像是你的设计的问题。 Class instantiation has to be fast and if you do long-running operations within it, you break against a bunch of best practices and need to refactor your code base rather than looking for ways to hack around it类实例化必须很快,如果你在其中进行长时间运行的操作,你就会违反一系列最佳实践,需要重构你的代码库而不是寻找绕过它的方法

I got the same problem and I find Andrew Lock blog: https://andrewlock.net/running-async-tasks-on-app-startup-in-asp-net-core-3/我遇到了同样的问题,我找到了 Andrew Lock 博客: https : //andrewlock.net/running-async-tasks-on-app-startup-in-asp-net-core-3/

He explains how to do this with asp .net core 3, but he also refers to his pages on how to to this with previous version.他解释了如何使用 asp .net core 3 执行此操作,但他还参考了有关如何使用先前版本执行此操作的页面。

Adding detail to Jérôme FLAMEN's answer, as it provided the key I required to calling an async Initialization task to a singleton:在 Jérôme FLAMEN 的回答中添加细节,因为它提供了我将异步初始化任务调用到 singleton 所需的密钥:

Create a class that implements IHostedService:创建一个实现 IHostedService 的 class:

public class PostStartup : IHostedService
{
   private readonly YourSingleton yourSingleton;

   public PostStartup(YourSingleton _yourSingleton)
   {
       yourSingleton = _yourSingleton;
   }

   // you may wish to make use of the cancellationToken
   public async Task StartAsync(CancellationToken cancellationToken)
   {
      await yourSingleton.Initialize();
   }

   // implement as you see fit
   public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}

Then, in your ConfigureServices , add a HostedService reference:然后,在您的ConfigureServices中,添加一个HostedService引用:

services.AddHostedService<PostStartup>();

From link .来自链接

I made some manager and I need to subscribe to events of the other services.我做了一些管理器,我需要订阅其他服务的事件。 I didn't like doing this in the我不喜欢在

webBuilder.Configure (applicationBuilder => ...

I think it should be in the section我认为它应该在该部分

webBuilder.ConfigureServices ((context, services) => ...

So, here is my answer (test on net.core 3):所以,这是我的答案(在 net.core 3 上测试):

public static IHostBuilder CreateHostBuilder (string [] args) =>
    Host.CreateDefaultBuilder (args)
        .ConfigureWebHostDefaults (webBuilder =>
        {

        ...

        services.AddSingleton<ISomeSingletonService,SomeSingletonService>();

        var buildServiceProvider = services.BuildServiceProvider();
        var someSingletonService = buildServiceProvider.GetRequiredService <ISomeSingletonService>();

        ...
        });
  

Lately I've been creating it as an IHostedService if it needs initialization, because to me it seems more logical to let the initialization be handled by the service itself rather than outside of it.最近,如果它需要初始化,我一直将它创建为IHostedService ,因为对我来说,让服务本身而不是服务外部处理初始化似乎更合乎逻辑。

You can even use a BackgroundService instead of IHostedService as it's pretty similar and it only needs the implementation of ExecuteAsync您甚至可以使用BackgroundService而不是IHostedService因为它非常相似并且只需要实现ExecuteAsync

Here's the documentation for them这是他们的文档
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services

An example of how to add the service so you can inject it directly:如何添加服务以便您可以直接注入它的示例:

services
    .AddHostedService<MyService>()
    .AddSingleton<MyService>(x => x
        .GetServices<IHostedService>()
        .OfType<MyService>()
        .First());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM