【问题标题】:Initialize a singleton after configuring dependency injection, but before the first http request在配置依赖注入之后,但在第一个 http 请求之前初始化一个单例
【发布时间】:2019-06-02 23:30:59
【问题描述】:

我使用的是 Azure Functions 版本 2.x。它有built-in support for dependency injection

所以我可以使用以下方法在单例范围内为 DI 注册我的服务 IMyService:

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddSingleton<IOther, DefaultOther>();
        builder.Services.AddSingleton<IMyService, DefaultMyService>();  // IMyService depends on IOther.
    }
}

DefaultMyService 的实例在函数第一次执行时创建。这意味着第一个请求较慢,因为它会在 DefaultMyService 内部进行大量初始化(它填充缓存等)。

问题:有没有办法在第一次请求之前创建DefaultMyService

similar question 询问了 asp.net 核心,那里的答案提出了一些解决方案,但它们都不适用于函数应用程序的上下文:

选项1:创建我的服务的实例(初始化发生在这里),然后注册实例(而不是注册类型)

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

这不起作用,因为在我的情况下IMyService 依赖于其他服务,这些服务在我在Configure 方法中注册IMyService 时没有实例化。它失败并出现here 描述的错误。

选项 2:其他建议是使用重载的配置方法:

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

这也不起作用,因为在函数应用的情况下,唯一执行的配置方法是Configure(IFunctionsHostBuilder builder),并且不会调用其他重载。

【问题讨论】:

  • 部署后,安排诊断方法调用。这不仅会测试健康状况,还会让函数处于 warm 状态,为第一次客户端调用做准备
  • 其他依赖项是如何/在哪里注册的?
  • @Nkosi 使用相同的方法,但在 IMyService 之前。它还依赖于 ILoggerFactory,它在调用 Configure 之前由函数应用程序主机预先注册。我编辑了有问题的代码示例以使其更清晰。

标签: c# dependency-injection azure-functions


【解决方案1】:

因为它会在 DefaultMyService 内部进行大量初始化

这就是问题的核心所在。正如 Mark Seemann 解释的here,注入构造函数不应该做更多的检查 null 和存储传入的依赖项。任何时候你在构造函数中进行任何 I/O 或调用类的依赖项内部,你都会遇到麻烦。

您的问题似乎类似于this q/a,我的建议是一样的:从构造函数中提取初始化逻辑,然后执行以下操作:

  • 在连接对象图之前进行初始化,并为 DI 配置提供已初始化的对象,或者
  • 在注册阶段之后和第一次请求之前直接解析和调用对象图,以便可以初始化数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-28
    • 2013-07-22
    • 1970-01-01
    • 2013-12-10
    • 1970-01-01
    • 2011-04-19
    • 1970-01-01
    相关资源
    最近更新 更多