You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Functions隔离模式下Scoped服务依赖注入异常咨询

问题原因

Azure Functions隔离模式里,IFunctionsWorkerMiddleware的实例是单例生命周期——宿主启动时就会初始化所有中间件,构造函数里注入的服务会从根服务容器解析。而根容器不支持Scoped作用域,这里的Scoped服务会被当成Transient处理,每次解析都新建实例。

而你的函数类是在每次请求的独立作用域里被解析的,这里的Service1才是真正的Scoped实例。两边的实例来源不同,自然会出现每次请求创建两个Service1的情况。

另外你的中间件代码还有个小bug:构造函数里的service1 = service1;是无效赋值,应该是_service1 = service1;,不过这不会影响实例数量,但会导致中间件里的_service1始终为null。

修复方案

核心思路是:不在中间件构造函数注入Scoped服务,而是在请求执行时从当前作用域获取。

修改后的TestMiddleware代码

public class TestMiddleware : IFunctionsWorkerMiddleware
{
    public TestMiddleware()
    {
        Console.WriteLine("TestMiddleware constructor");
    }

    public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    {
        // 从当前请求的作用域中获取Scoped的Service1实例
        var service1 = context.InstanceServices.GetRequiredService<Service1>();
        // 这里可以使用service1做逻辑处理
        await next(context);
    }
}

其他代码保持不变

  • Service1类无需修改;
  • Program.cs里的services.AddScoped<Service1>();注册保留;
  • TestFunction的构造函数注入Service1的逻辑也不用改。

这样调整后,每次请求只会创建一个Service1实例,中间件和函数会复用同一个实例,符合Scoped服务的预期行为。

关键注意事项

在Azure Functions隔离模式中,所有中间件默认都是单例注册的,所以绝对不能在中间件构造函数中注入Scoped或Transient服务——这会让服务被绑定到根容器的生命周期,完全失去Scoped的特性。正确的做法是在Invoke方法里通过FunctionContext.InstanceServices获取当前请求作用域内的服务。

内容的提问来源于stack exchange,提问作者Kadir Alan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 21:50:34