AzureFunctionsでDIコンテナを利用する【C#】
AzureFunctionsでDIコンテナを利用する
一応v2のお話です。v1でもあらかた使えるっぽいけど未検証です。
一般的なアプリケーションのDIコンテナでは、アプリ起動時にDIコンテナへ型情報やインスタンス生成方法を詰め込み、必要に応じてインスタンスを取り出して利用します。Azure FunctionsではFunction単位での実行、呼び出しとなるため、Functionが呼び出される前に引数へのバインドを行う必要があります。普通はカスタムバインディングスを作成して実現するのですが、地味に必要なコードが多くて面倒です。
その手間をいい感じに解決してくれるDIコンテナライブラリが「AzureFunctions.Autofac」です。
NuGet Gallery | AzureFunctions.Autofac 3.0.5
https://www.nuget.org/packages/AzureFunctions.Autofac
introtocomputerscience/azure-function-autofac-dependency-injection
https://github.com/introtocomputerscience/azure-function-autofac-dependency-injection
サンプルコード
コメントでいろいろ補足しつつサンプルコードをば。
// DI設定を付与したいFunctionにこの属性を付与する!
// 引数で指定する型を変更することで、複数のDIConfigを使い分けることが出来る!
[DependencyInjectionConfig(typeof(DIConfig))]
public static class GetPlayerVoiceFunction
{
[FunctionName("GetPlayerVoice")]
public static IActionResult Run(
[HttpTrigger("get")] HttpRequest req,
ILogger log,
[Inject] IPlayerVoiceService service) // Functionの引数にインジェクトしたい場合、Inject属性が必要だよ!
{
// => serviceの実装型は「PlayerVoiceService」です!
log.LogInformation($"serviceの実装型は「{service.GetType().Name}」です!");
var playerVoice = service.GetPlayerVoice();
// => PlayerVoice=スプラトゥーン楽しいいいいいいいいい
log.LogInformation($"PlayerVoice={playerVoice}");
return new OkObjectResult(playerVoice);
}
}
public class DIConfig
{
public DIConfig(string functionName)
{
DependencyInjection.Initialize(builder =>
{
// インターフェイスと、それに対応する実装クラスを指定!
// いろんな設定方法があるので、本家Autofacを参考にしてね!
// https://github.com/autofac/Autofac#get-started
builder.RegisterType<InMemoryPlayerVoiceRepository>().As<IPlayeVoiceRepository>();
builder.RegisterType<PlayerVoiceService>().As<IPlayerVoiceService>();
},
functionName);
}
}
public interface IPlayeVoiceRepository
{
string Get();
}
public class InMemoryPlayerVoiceRepository : IPlayeVoiceRepository
{
public string Get() => "スプラトゥーン楽しいいいいいいいいい";
}
public interface IPlayerVoiceService
{
string GetPlayerVoice();
}
public class PlayerVoiceService : IPlayerVoiceService
{
private readonly IPlayeVoiceRepository repository;
// PlayerVoiceServiceとInMemoryRepositoryの両方を登録しているので、
// コンストラクタ引数へInMemoryRepositoryのインスタンスをインジェクトしてくれるよ!
// Functionの引数じゃないのでInject属性は不要だよ!
public PlayerVoiceService(IPlayeVoiceRepository repository)
{
this.repository = repository;
}
public string GetPlayerVoice()
{
return repository.Get();
}
}
便利ですね!
他にも出来ることはたくさんあります。せっかくのオープンソースなのでリポジトリのReadme読んでみたり、Autofacそのものについて調べると幸せになれるかも。
全文はGistにあげてます。
https://gist.github.com/kokeiro001/b7fc8ac08b3c7854f7914f65ee8da9b7
ILoggerの取り回しについて
エンドポイントとなるFunctionメソッドの引数にILoggerを指定すると、Azure Functions側でロガーインスタンスを提供してくれます。標準機能ですね。このロガーに対して書き込みを行うとAzure Table Storageに保存され、ポータル上などから閲覧することができます。
このILoggerを他のクラスでもInjectしたい欲求は非常に強いです。が、私はこの方法分かってません。v1時代やとある時期までのv2ではできたっぽいんですけどね。そのへんのやり取りは公式リポジトリのissueで行われてます。
Add support for injecting the Function provided ILogger into own DI Framework · Issue #2720 · Azure/azure-functions-host
https://github.com/Azure/azure-functions-host/issues/2720
現状の代替案としては、適当なTable Storageなどに保存するオレオレLoggerを作って取り回す感じでしょうか。標準ポータルから見れないのはちと残念ですが。なにかいい方法知ってる人いたら教えて下しあ。
おまけ
ざっくりとした実践としてオレオレライフロガーのリポジトリを貼っときます。
しっかり動かすには対応するIoT機器とか外部サービス設定が必要なので、ソースコード眺める程度にはなりますがドウゾ。
参考
AzureFunctions.Autofacのソースコードを読む場合、先にカスタムバインディングスについて学んでおくと理解がスムーズです。
Azure Functions の Custom Bindings を開発する - Qiita
https://qiita.com/TsuyoshiUshio@github/items/345887a5fa5d59e7444a
Author And Source
この問題について(AzureFunctionsでDIコンテナを利用する【C#】), 我々は、より多くの情報をここで見つけました https://qiita.com/kokeiro001/items/aee61bb4ee1591fe2847著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .