在Azure Logic Apps自定义代码中实现依赖注入的问题求助
.NET 8孤立模式Logic Apps自定义函数依赖注入配置方案
问题背景
通过VS Code创建包含自定义.NET 8孤立模式Azure Function的Azure Logic Apps工作区,函数可在工作流中正常运行,但无法配置依赖注入:
- 常规孤立模式Function通过
Program.cs配置宿主,但项目中无此文件 - 尝试创建进程模式适用的
Startup.cs无效 - 推测宿主构建流程被封装在
Microsoft.Azure.Workflows.Functions.CustomCodeNetFxWorker.exe进程中,当前仅ILoggerFactory已注册
重现步骤
- 打开已安装Azure Logic Apps、Azurite扩展的Visual Studio Code
- 在Azure扩展中创建Azure Logic Apps工作区
- 选择带自定义项目的Logic Apps,其余保持默认值
- 项目仅包含示例函数(代码如下):
namespace My.Fun { using System; using System.Threading.Tasks; using Microsoft.Azure.Functions.Extensions.Workflows; using Microsoft.Azure.Functions.Worker; using Microsoft.Extensions.Logging; /// <summary> /// Represents the function flow invoked function. /// </summary> public class function { private readonly ILogger<function> logger; public function(ILoggerFactory loggerFactory) { logger = loggerFactory.CreateLogger<function>(); } /// <summary> /// Executes the logic app workflow. /// </summary> /// <param name="zipCode">The zip code.</param> /// <param name="temperatureScale">The temperature scale (e.g., Celsius or Fahrenheit).</param> [Function("function")] public Task<Weather> Run([WorkflowActionTrigger] int zipCode, string temperatureScale) { this.logger.LogInformation("Starting function with Zip Code: " + zipCode + " and Scale: " + temperatureScale); // Generate random temperature within a range based on the temperature scale Random rnd = new Random(); var currentTemp = temperatureScale == "Celsius" ? rnd.Next(1, 30) : rnd.Next(40, 90); var lowTemp = currentTemp - 10; var highTemp = currentTemp + 10; // Create a Weather object with the temperature information var weather = new Weather() { ZipCode = zipCode, CurrentWeather = $"The current weather is {currentTemp} {temperatureScale}", DayLow = $"The low for the day is {lowTemp} {temperatureScale}", DayHigh = $"The high for the day is {highTemp} {temperatureScale}" }; return Task.FromResult(weather); } } public class Weather { public int ZipCode { get; set; } public string CurrentWeather { get; set; } public string DayLow { get; set; } public string DayHigh { get; set; } } }
- 可观察到
ILogger已注册可用,但无Startup.cs或Program.cs用于扩展服务集合
解决方案
步骤1:创建宿主启动扩展类
实现IFunctionsWorkerApplicationBuilderStartup接口,并通过程序集级别属性标记,让宿主启动时自动加载该扩展:
using Microsoft.Azure.Functions.Worker; using Microsoft.Extensions.DependencyInjection; // 程序集级别标记,指定启动扩展类 [assembly: FunctionsWorkerApplicationBuilderStartup(typeof(My.Fun.WorkerStartup))] namespace My.Fun { public class WorkerStartup : IFunctionsWorkerApplicationBuilderStartup { public void Configure(FunctionsWorkerApplicationBuilder builder) { // 在此注册你的依赖服务,示例: // 注册Scoped服务(每次函数执行创建实例) builder.Services.AddScoped<IMyService, MyService>(); // 注册Singleton服务(全局唯一实例) // builder.Services.AddSingleton<IMySingletonService, MySingletonService>(); } } // 示例服务接口与实现 public interface IMyService { string GetServiceMessage(); } public class MyService : IMyService { public string GetServiceMessage() { return "来自自定义依赖服务的消息"; } } }
步骤2:在函数类中注入依赖
修改函数类的构造函数,直接注入已注册的服务:
namespace My.Fun { using System; using System.Threading.Tasks; using Microsoft.Azure.Functions.Extensions.Workflows; using Microsoft.Azure.Functions.Worker; using Microsoft.Extensions.Logging; public class function { private readonly ILogger<function> _logger; private readonly IMyService _myService; // 构造函数注入ILoggerFactory和自定义服务 public function(ILoggerFactory loggerFactory, IMyService myService) { _logger = loggerFactory.CreateLogger<function>(); _myService = myService; } [Function("function")] public Task<Weather> Run([WorkflowActionTrigger] int zipCode, string temperatureScale) { this._logger.LogInformation("Starting function with Zip Code: " + zipCode + " and Scale: " + temperatureScale); // 使用自定义服务 this._logger.LogInformation(_myService.GetServiceMessage()); // 原有业务逻辑... Random rnd = new Random(); var currentTemp = temperatureScale == "Celsius" ? rnd.Next(1, 30) : rnd.Next(40, 90); var lowTemp = currentTemp - 10; var highTemp = currentTemp + 10; var weather = new Weather() { ZipCode = zipCode, CurrentWeather = $"The current weather is {currentTemp} {temperatureScale}", DayLow = $"The low for the day is {lowTemp} {temperatureScale}", DayHigh = $"The high for the day is {highTemp} {temperatureScale}" }; return Task.FromResult(weather); } } }
原理说明
Logic Apps的自定义函数宿主虽被封装,但仍支持通过IFunctionsWorkerApplicationBuilderStartup接口扩展服务集合。程序集级别的FunctionsWorkerApplicationBuilderStartup属性会告诉宿主在启动时执行指定类的Configure方法,从而完成依赖服务的注册。
注意事项
- 服务生命周期选择:根据函数执行模型,推荐使用
Scoped生命周期(每次函数执行创建新实例),Singleton适用于全局共享的服务 - 确保项目已引用必要的NuGet包:
Microsoft.Azure.Functions.Worker、Microsoft.Azure.Functions.Worker.Extensions.Workflows(默认创建项目已包含)
内容的提问来源于stack exchange,提问作者Cijun Zhu
相关产品推荐
相关产品推荐

