C# ASP.NET内核在配置DI后初始化单例

C# ASP.NET内核在配置DI后初始化单例,c#,asp.net-core,dependency-injection,singleton,C#,Asp.net Core,Dependency Injection,Singleton,假设我在DI中注册了一个单例类实例,如下所示: services.AddSingleton<IFoo, Foo>(); services.AddSingleton(); 让我们假设Foo类有许多其他依赖项(主要是允许它加载数据的存储库类) 根据我目前的理解,Foo实例在第一次使用(询问)之前是不会创建的。除了构造函数之外,还有其他方法初始化这个类吗?像是在ConfigureServices()完成之后?或者应该在Foo的构造函数中完成初始化代码(从db加载数据) (如果这个类可以

假设我在DI中注册了一个单例类实例,如下所示:

services.AddSingleton<IFoo, Foo>();
services.AddSingleton();
让我们假设
Foo
类有许多其他依赖项(主要是允许它加载数据的存储库类)

根据我目前的理解,Foo实例在第一次使用(询问)之前是不会创建的。除了构造函数之外,还有其他方法初始化这个类吗?像是在
ConfigureServices()
完成之后?或者应该在Foo的构造函数中完成初始化代码(从db加载数据)


(如果这个类可以在第一次使用之前加载它的数据,以加速第一次访问,那就太好了)

在启动时自己动手

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

但是如果你在构造器中做了一些你不应该做的事情,这会让你感觉脏兮兮的,对你的设计来说更是个问题。类实例化必须很快,如果你在其中执行长时间运行的操作,你会违反一系列最佳实践,需要重构你的代码库,而不是寻找方法来破解它

我也遇到了同样的问题,我发现Andrew Lock的博客:


他解释了如何使用asp.net core 3实现这一点,但他也提到了如何使用早期版本实现这一点的页面。

我做了一些管理,我需要订阅其他服务的事件。 我不喜欢在晚上这样做

webBuilder.Configure (applicationBuilder => ...
我想应该在这一部分

webBuilder.ConfigureServices ((context, services) => ...
下面是我的答案(在net.core 3上测试):

公共静态IHostBuilder CreateHostBuilder(字符串[]args)=>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder=>
{
...
services.AddSingleton();
var buildServiceProvider=services.buildServiceProvider();
var someSingletonService=buildServiceProvider.GetRequiredService();
...
});

您可以创建
new Foo()
并在
ConfigureServices
方法中注册它。@ademcaglin这不起作用;因为
Foo
有依赖项,所以它不会有默认的构造函数。但是我不得不担心Foo的所有依赖项(所有存储库及其依赖项)。当然是可行的,但是寻找一种不与系统对抗的方法。是的。您通常只初始化需要特殊处理的类,比如启动服务总线连接等,而这是您不希望在启动时发生的。我们需要更多的信息,尽管你到底在尝试什么。我怀疑您在构造函数中执行了一些长时间运行的操作,这是绝对不可能的。类实例化应该是在构造函数中从未完成的快速且长时间运行的操作。当然,您也可以在
Configure
中解析该类一次,但这对我来说只是感觉“脏”了它是
public void-Configure(iaapplicationbuilder-app){app.ApplicationServices.GetService();}
(IFoo而不是Foo)如果您的单例服务需要从文件读取数据或从数据库加载数据并充当该数据的缓存,该怎么办?在第一次请求时(当请求服务时)这样做似乎是不对的,但对我来说,这似乎是一种常见的情况。此外,这些操作具有潜在的危险性,可能引发您希望捕获、记录等的异常。如果自己实例化服务或“预热”感觉脏了,那么执行此操作的最佳做法是什么?@CollinBarrett:disposition发生在容器被处置时。对于应用程序正常关闭时的单例(因为单例来自应用程序容器)Hiérôme FLAMEN,欢迎。请考虑添加更多的信息,因为如果链接过时了,那么你的答案非常低。感谢文章的引用,但是在我的主要方法中,我的WebHuST正在被初始化:CreateWebHostBuilder(ARGs)。因此,我调用的是Run方法,而不是StartAsync方法。我不认为调用异步方法而不是同步方法是一个问题(因为我可以捕获结果任务并等待它),但是调用Run和Start之间有区别吗?
webBuilder.Configure (applicationBuilder => ...
webBuilder.ConfigureServices ((context, services) => ...
public static IHostBuilder CreateHostBuilder (string [] args) =>
    Host.CreateDefaultBuilder (args)
        .ConfigureWebHostDefaults (webBuilder =>
        {

        ...

        services.AddSingleton<ISomeSingletonService,SomeSingletonService>();

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

        ...
        });