Azure App Functions 3.0:如何向非函数类注入ILogger等单例服务
Azure App Functions 3.0 ILogger 依赖注入解决方案
核心问题原因
- 手动
new LoggerFactory未绑定Azure Functions默认的日志输出提供程序(控制台、Application Insights等),生成的Logger没有输出通道,日志无法落盘/上报 - 混用Ninject和Azure Functions原生DI容器时,未正确桥接ILogger的解析逻辑,导致拿到的Logger实例未绑定正确的上下文
ActivatorUtilities.CreateInstance<ILogger>无法直接实例化抽象接口ILogger,写法本身不合法
标准解决方案(推荐使用原生DI,无需混用Ninject)
第一步:引入依赖并配置启动类
首先安装NuGet包Microsoft.Azure.Functions.Extensions,然后按规范编写Startup类:
using Microsoft.Azure.Functions.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; // 标记启动类 [assembly: FunctionsStartup(typeof(YourNamespace.Startup))] namespace YourNamespace { public class Startup : FunctionsStartup { public override void Configure(IFunctionsHostBuilder builder) { // 注册你的内部服务,原生DI会自动处理ILogger的注入 builder.Services.AddScoped<MyInternalClass>(); // 无需额外注册ILogger,Azure Functions运行时默认已经完成了日志相关服务的注册 } } }
第二步:内部类构造函数注入ILogger
直接在需要用日志的类的构造函数中声明依赖即可,不需要手动获取ServiceProvider:
public class MyInternalClass { private readonly ILogger<MyInternalClass> _logger; // DI容器会自动注入绑定了当前上下文的Logger实例 public MyInternalClass(ILogger<MyInternalClass> logger) { _logger = logger; } public void ProcessTicket(string ticket) { _logger.LogInformation($"Information Ticket: {ticket} | Data: ..."); } }
第三步:函数入口注入内部类直接调用
函数类中直接注入内部服务,无需逐层传递Logger:
public class YourFunction { private readonly MyInternalClass _internalClass; public YourFunction(MyInternalClass internalClass) { _internalClass = internalClass; } [FunctionName("TestFunction")] public async Task<IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req) { // 直接调用内部类方法,日志会正常输出到Azure Functions日志面板、Application Insights _internalClass.ProcessTicket("TICKET_001"); return new OkObjectResult("Success"); } }
兼容Ninject的解决方案
如果项目必须保留Ninject作为DI容器,只需要在启动时桥接原生ILogger的解析逻辑即可:
// Startup.cs Configure方法中 public override void Configure(IFunctionsHostBuilder builder) { // 先构建原生服务提供者 var nativeServiceProvider = builder.Services.BuildServiceProvider(); // 把ILogger的解析桥接到原生容器 NinjectKernel._kernel.Bind(typeof(ILogger<>)).ToMethod(context => { var genericType = typeof(ILogger<>).MakeGenericType(context.GenericArguments[0]); return nativeServiceProvider.GetService(genericType); }); NinjectKernel._kernel.Bind<ILogger>().ToMethod(context => { var loggerFactory = nativeServiceProvider.GetService<ILoggerFactory>(); return loggerFactory.CreateLogger("InfoLogger"); }); // 后续注册你自己的其他服务即可 }
内容的提问来源于stack exchange,提问作者zion
相关产品推荐
相关产品推荐

