在配置依赖项注入之后但在第一个http请求之前,初始化一个单例

时间:2019-06-02 23:30:59

标签: c# dependency-injection azure-functions

我正在使用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依赖于其他服务,这些服务在我在IMyService方法中注册Configure时未实例化。它失败,并显示描述为here的错误。

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

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

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

1 个答案:

答案 0 :(得分:2)

  

因为它完成了DefaultMyService内部的大量初始化

这是问题的核心所在。正如Mark Seemann解释的here一样,注入构造函数不应该做其他任何检查null并存储传入依赖项的事情。每当您执行任何I / O或在构造函数内部 调用类的依赖项时,都会遇到麻烦。

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

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