概要
Azure Functions にて .NET Core で開発する際において、DIを用いた実装方法について纏めます。
ASP.NET Core にて利用したように、Serviceインスタンスの依存関係注入がやり易い形になっています。
公式のドキュメントは、下記になります。
https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-dotnet-dependency-injection
以下、記事を参考にさせていただきました。
https://blog.shibayan.jp/entry/20190520/1558340113
https://qiita.com/HiroyukiSakoh/items/e9e472a92a53da4d7568
環境
- Azure Functions v3
- Windows10
- Visual Studio 2019
- .NET Core 3.1
コードサンプル
サンプルコードを Github にアップしています。
https://github.com/tYoshiyuki/azure-functions-di-sample
(※) コードサンプルを Azure Functions v3 に更新しました。
解説
公式の記事の通り、Microsoft.Azure.Functions.Extensions を Nuget より取得し、プロジェクトに加えます。
https://www.nuget.org/packages/Microsoft.Azure.Functions.Extensions/
Startup.cs にて DI の設定を行います。
実装例として、設定ファイルの読み込みとサービスのDI設定を行っています。
[assembly: FunctionsStartup(typeof(Startup))]
namespace AzureFunctionsDiSample
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
var services = builder.Services;
var provider = services.BuildServiceProvider();
var configuration = provider.GetRequiredService<IConfiguration>();
// 設定ファイルの内容をバインドする
services.Configure<AppSettings>(configuration.GetSection("AppSettings"));
// サービスのDI設定を行う
services.AddTransient<IHelloService, HelloService>();
services.AddTransient<IApplication, Application>();
}
}
}
コードサンプルは、以下のようにクラスのレイヤー分けを行っています。
クラス名 | 説明 |
---|---|
EntryPoint | Azure Functions のエントリーポイント |
Application | メインとなるアプリケーション |
HelloService | ビジネスロジックサービス |
Azure Functions のエントリーポイントとなるクラス (EntryPoint.cs) から、
実際のアプリケーション処理を行うクラス、サービス処理を行うクラスを別レイヤーに切り出しています。
これにより、エントリーポイントとアプリケーションの依存関係を分離し、ユニットテストを実施し易い形にしています。
DIで設定したインスタンスは、コンストラクタインジェクションで受け取ります。
ASP.NET Core で利用する形と同じようなイメージになります。
public EntryPoint(IApplication application)
{
_application = application;
}
[FunctionName("FunctionsDiSample")]
public IActionResult Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("Function Run");
_application.Run();
return new OkObjectResult("Hello Functions DI Sample");
}
EntryPointでは Application を受け取り、また同様に Application では HelloService を受け取ります。
設定ファイルについては、IOptionsで受け取れます。
private readonly AppSettings _appSettings;
private readonly IHelloService _service;
public Application(ILogger<IApplication> logger, IOptions<AppSettings> optionsAccessor, IHelloService service) : base(logger)
{
_appSettings = optionsAccessor.Value;
_service = service;
}
ASP.NET Core で開発する際に意識するような クラスのレイヤー分け のノウハウが、
Azure Functionsでも生かせるようになり、今後の開発の幅が広がると思います。