问题描述
我使用的是 Azure Functions 版本 2.x.它具有对依赖注入的内置支持.
I am using Azure Functions version 2.x. It has built-in support for dependency injection.
所以我可以使用以下方法在单例范围内为 DI 注册我的服务 IMyService:
So I can register my service IMyService for DI at singleton scope using:
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
内部进行大量初始化(它填充缓存等).
An instance of DefaultMyService
is created the first time the function gets executed. This means the first request is slower because it does heavy initialization that happens inside DefaultMyService
(it populates cache, etc.).
问题:有没有办法让 DefaultMyService
在第一次请求之前创建?
Question: Is there a way to have DefaultMyService
created earlier than the first request?
向 asp.net 询问了 类似问题核心,那里的答案提出了一些解决方案,但它们都不适用于函数应用程序的上下文:
A similar question was asked for asp.net core, and the answers there suggests a few solutions, but none of them works in the context of a function app:
选项1:创建我的服务的实例(初始化发生在这里),然后注册实例(而不是注册类型)
Option 1: Create an instance of my service (initialization happens here), and then register the instance (instead of registering the type)
var foo = new Foo();
services.AddSingleton<IFoo>(foo);
这不起作用,因为在我的情况下 IMyService
依赖于其他服务,这些服务在我在 Configure 中注册
方法.它失败并出现 此处描述的错误.IMyService
时未实例化
This doesn't work because in my case IMyService
depends on other services, which are not instantiated at the time when I am registering IMyService
in the Configure
method. It fails with an error that's described here.
选项 2:其他建议是使用重载的配置方法:
Option 2: Other suggestion is to use overloaded Configure method:
public void Configure(IApplicationBuilder app, IFoo foo)
{
...
}
这也不起作用,因为在函数应用的情况下,唯一执行的配置方法是 Configure(IFunctionsHostBuilder builder)
,并且不会调用其他重载.
This also doesn't work because in case of function app, the only configure method that gets executed is Configure(IFunctionsHostBuilder builder)
, and other overloads are not called.
推荐答案
因为它会在 DefaultMyService 内部进行大量初始化
because it does heavy initialization that happens inside DefaultMyService
这就是问题的核心所在.正如 Mark Seemann here 解释的那样,注入构造函数不应该再检查 null并存储传入的依赖项.任何时候你在构造函数中进行任何 I/O 或调用类的依赖项内部,你都会遇到麻烦.
This is where the core of the problem lies. As Mark Seemann explained here, Injection constructors should do nothing more checking for null and storing incoming dependencies. Any time you do any I/O or invoke the class's dependencies inside the constructor, you'll get in trouble.
您的问题似乎类似于 this q/a,我的建议是一样的:从构造函数中提取初始化逻辑,然后执行以下操作:
Your question seems similar to this q/a, and my advise would be the same: extract the initialization logic out of the constructor and either do the following:
- 在连接对象图之前进行初始化,并为 DI 配置提供初始化对象,或者
- 在注册阶段之后、第一次请求之前直接解析和调用对象图,以使数据可以初始化.
这篇关于在配置依赖注入之后,但在第一个 http 请求之前初始化一个单例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!