.NET Azure Functions で依存関係の挿入を使用するUse dependency injection in .NET Azure Functions

Azure Functions では、依存関係の挿入 (DI) ソフトウェア デザイン パターンがサポートされています。これは、クラスと依存関係の間で制御の反転 (IoC) を実現するための技術です。Azure Functions supports the dependency injection (DI) software design pattern, which is a technique to achieve Inversion of Control (IoC) between classes and their dependencies.

  • Azure Functions の依存関係挿入は、.NET Core の依存関係挿入機能を基盤としています。Dependency injection in Azure Functions is built on the .NET Core Dependency Injection features. .NET Core 依存関係挿入について理解しておくことをお勧めします。Familiarity with .NET Core dependency injection is recommended. 依存関係のオーバーライド方法と、従量課金プランで Azure Functions により構成値を読み取る方法に違いがあります。There are differences in how you override dependencies and how configuration values are read with Azure Functions on the Consumption plan.

  • 依存関係の挿入のサポートは、Azure Functions 2.x から開始されます。Support for dependency injection begins with Azure Functions 2.x.

前提条件Prerequisites

依存関係の挿入を使用する前に、次の NuGet パッケージをインストールする必要があります。Before you can use dependency injection, you must install the following NuGet packages:

サービスを登録するRegister services

サービスを登録するには、構成用のメソッドを作成し、IFunctionsHostBuilder インスタンスにコンポーネントを追加します。To register services, create a method to configure and add components to an IFunctionsHostBuilder instance. Azure Functions ホストにより、IFunctionsHostBuilder のインスタンスが作成され、メソッドに直接渡されます。The Azure Functions host creates an instance of IFunctionsHostBuilder and passes it directly into your method.

このメソッドを登録するには、起動時に使用される型名を指定する FunctionsStartup アセンブリ属性を追加します。To register the method, add the FunctionsStartup assembly attribute that specifies the type name used during startup.

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(MyNamespace.Startup))]

namespace MyNamespace
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddHttpClient();

            builder.Services.AddSingleton<IMyService>((s) => {
                return new MyService();
            });

            builder.Services.AddSingleton<ILoggerProvider, MyLoggerProvider>();
        }
    }
}

この例では、スタートアップ時に HttpClient を登録するために必要な Microsoft.Extensions.Http パッケージが使用されています。This example uses the Microsoft.Extensions.Http package required to register an HttpClient at startup.

注意事項Caveats

ランタイム前後の一連の登録手順実行によりスタートアップ クラスが処理されます。A series of registration steps run before and after the runtime processes the startup class. そのため、以下の点に注意してください。Therefore, keep in mind the following items:

  • スタートアップ クラスは設定と登録だけを目的とします。The startup class is meant for only setup and registration. スタートアップ プロセス中、スタートアップ時に登録されるサービスを使用しないでください。Avoid using services registered at startup during the startup process. たとえば、スタートアップ中に登録されているロガーにメッセージを記録しないでください。For instance, don't try to log a message in a logger that is being registered during startup. 登録プロセスのこの時点は、サービスを利用するには早すぎます。This point of the registration process is too early for your services to be available for use. Configure メソッドが実行されると、Functions ランタイムは追加の依存関係を引き続き登録します。これがサービスの動作に影響を与える可能性があります。After the Configure method is run, the Functions runtime continues to register additional dependencies, which can affect how your services operate.

  • 依存関係挿入コンテナーでは、明示的に登録された型のみが保持されますThe dependency injection container only holds explicitly registered types. 挿入可能な型として利用できる唯一のサービスは Configure メソッド内で設定されるサービスです。The only services available as injectable types are what are setup in the Configure method. 結果的に、BindingContextExecutionContext のような Functions 固有の型は設定中に利用できず、また、挿入可能な型として利用できません。As a result, Functions-specific types like BindingContext and ExecutionContext aren't available during setup or as injectable types.

挿入された依存関係を使用するUse injected dependencies

コンストラクターの挿入は、依存関係を関数で利用できるようにする目的で使用されます。Constructor injection is used to make your dependencies available in a function. コンストラクターの挿入を使用するには、挿入されたサービスまたは関数クラスに対して静的クラスを使用しないようにする必要があります。The use of constructor injection requires that you do not use static classes for injected services or for your function classes.

次のサンプルでは、IMyServiceHttpClient の依存関係が、HTTP によってトリガーされる関数にどのように挿入されるかを示します。The following sample demonstrates how the IMyService and HttpClient dependencies are injected into an HTTP-triggered function.

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using System.Net.Http;
using System.Threading.Tasks;

namespace MyNamespace
{
    public class MyHttpTrigger
    {
        private readonly HttpClient _client;
        private readonly IMyService _service;

        public MyHttpTrigger(HttpClient httpClient, IMyService service)
        {
            this._client = httpClient;
            this._service = service;
        }

        [FunctionName("MyHttpTrigger")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            var response = await _client.GetAsync("https://microsoft.com");
            var message = _service.GetMessage();

            return new OkObjectResult("Response from function with injected dependencies.");
        }
    }
}

この例では、スタートアップ時に HttpClient を登録するために必要な Microsoft.Extensions.Http パッケージが使用されています。This example uses the Microsoft.Extensions.Http package required to register an HttpClient at startup.

サービスの有効期間Service lifetimes

Azure Functions アプリのサービス有効期間は ASP.NET 依存関係挿入と同じになります。Azure Functions apps provide the same service lifetimes as ASP.NET Dependency Injection. Functions アプリの場合、各種サービス有効期間が次のように動作します。For a Functions app, the different service lifetimes behave as follows:

  • 一時的:一時的なサービスは、サービスが要求されるたびに作成されます。Transient: Transient services are created upon each request of the service.
  • スコープ付き:スコープ付きサービスの有効期間は、関数実行の有効期間に一致します。Scoped: The scoped service lifetime matches a function execution lifetime. スコープ付きサービスは毎回作成されます。Scoped services are created once per execution. 実行時のそのサービスに対する後続の要求では、既存のサービス インスタンスが再利用されます。Later requests for that service during the execution reuse the existing service instance.
  • シングルトン:シングルトン サービスの有効期間はホストの有効期間に一致し、そのインスタンスでの関数実行間で再利用されます。Singleton: The singleton service lifetime matches the host lifetime and is reused across function executions on that instance. シングルトン サービスの有効期間は、DocumentClient インスタンスや HttpClient インスタンスなど、接続やクライアントに推奨されます。Singleton lifetime services are recommended for connections and clients, for example DocumentClient or HttpClient instances.

GitHub のさまざまなサービスの有効期間のサンプルを表示するか、ダウンロードします。View or download a sample of different service lifetimes on GitHub.

ログ記録サービスLogging services

独自のログ記録プロバイダーが必要な場合は、カスタム型を ILoggerProvider のインスタンスとして登録します。これは、Microsoft.Extensions.Logging.Abstractions NuGet パッケージを通じて使用できます。If you need your own logging provider, register a custom type as an instance of ILoggerProvider, which is available through the Microsoft.Extensions.Logging.Abstractions NuGet package.

Azure Functions によって Application Insights が自動的に追加されます。Application Insights is added by Azure Functions automatically.

警告

  • サービス コレクションに AddApplicationInsightsTelemetry() を追加しないでください。環境によって提供されるサービスと競合するサービスが登録されます。Do not add AddApplicationInsightsTelemetry() to the services collection as it registers services that conflict with services provided by the environment.
  • 組み込みの Application Insights 機能を使用している場合、独自の TelemetryConfiguration または TelemetryClient を登録しないでください。Do not register your own TelemetryConfiguration or TelemetryClient if you are using the built-in Application Insights functionality. 独自の TelemetryClient インスタンスを構成する必要がある場合は、「Azure Functions を監視する」に示されているように、挿入された TelemetryConfiguration を使用して作成します。If you need to configure your own TelemetryClient instance, create one via the injected TelemetryConfiguration as shown in Monitor Azure Functions.

ILogger および ILoggerFactoryILogger and ILoggerFactory

ホストでは、ILogger<T> サービスと ILoggerFactory サービスがコンストラクターに挿入されます。The host injects ILogger<T> and ILoggerFactory services into constructors. ただし、既定では、これらの新しいログ フィルターは関数のログから除外されます。However, by default these new logging filters are filtered out of the function logs. 追加のフィルターおよびカテゴリを選択するには、host.json ファイルを変更する必要があります。You need to modify the host.json file to opt-in to additional filters and categories.

次の例では、ホストに公開されるログを含む ILogger<HttpTrigger> を追加する方法を示します。The following example demonstrates how to add an ILogger<HttpTrigger> with logs that are exposed to the host.

namespace MyNamespace
{
    public class HttpTrigger
    {
        private readonly ILogger<HttpTrigger> _log;

        public HttpTrigger(ILogger<HttpTrigger> log)
        {
            _log = log;
        }

        [FunctionName("HttpTrigger")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req)
        {
            _log.LogInformation("C# HTTP trigger function processed a request.");

            // ...
    }
}

次の例の host.json ファイルでは、ログ フィルターが追加されます。The following example host.json file adds the log filter.

{
    "version": "2.0",
    "logging": {
        "applicationInsights": {
            "samplingSettings": {
                "isEnabled": true,
                "excludedTypes": "Request"
            }
        },
        "logLevel": {
            "MyNamespace.HttpTrigger": "Information"
        }
    }
}

関数アプリで提供されるサービスFunction app provided services

関数ホストは、多くのサービスを登録します。The function host registers many services. 次のサービスは、お使いのアプリケーションに依存関係として取り込んでも安全です。The following services are safe to take as a dependency in your application:

サービスの種類Service Type 有効期間Lifetime 説明Description
Microsoft.Extensions.Configuration.IConfiguration シングルトンSingleton 実行時の構成Runtime configuration
Microsoft.Azure.WebJobs.Host.Executors.IHostIdProvider シングルトンSingleton ホスト インスタンスの ID を提供する責任があるResponsible for providing the ID of the host instance

依存関係を取り込みたい他のサービスがある場合は、問題を作成し、GitHub でそれらを提案してくださいIf there are other services you want to take a dependency on, create an issue and propose them on GitHub.

ホスト サービスのオーバーライドOverriding host services

ホストによって提供されるサービスのオーバーライドは、現在サポートされていません。Overriding services provided by the host is currently not supported. オーバーライドしたいサービスがある場合は、問題を作成し、GitHub でそれらを提案してくださいIf there are services you want to override, create an issue and propose them on GitHub.

オプションと設定の使用Working with options and settings

アプリ設定に定義されている値は IConfiguration インスタンスで利用できます。それにより、スタートアップ クラスのアプリ設定値を読み取ることができます。Values defined in app settings are available in an IConfiguration instance, which allows you to read app settings values in the startup class.

IConfiguration インスタンスからカスタムの型に値を抽出できます。You can extract values from the IConfiguration instance into a custom type. アプリ設定値をカスタムの型にコピーすると、その値が挿入可能になり、サービスのテストが簡単になります。Copying the app settings values to a custom type makes it easy test your services by making these values injectable. 構成インスタンスに読み込まれる設定は、単純なキーと値のペアである必要があります。Settings read into the configuration instance must be simple key/value pairs.

次のクラスについて考えてください。名前がアプリ設定と一致するプロパティが含まれています。Consider the following class that includes a property named consistent with an app setting:

public class MyOptions
{
    public string MyCustomSetting { get; set; }
}

また、次のようにカスタム設定を構成する可能性のある local.settings.json ファイルもあります。And a local.settings.json file that might structure the custom setting as follows:

{
  "IsEncrypted": false,
  "Values": {
    "MyOptions:MyCustomSetting": "Foobar"
  }
}

Startup.Configure メソッド内から次のコードを使用し、IConfiguration インスタンスの値をカスタムの型に抽出することができます。From inside the Startup.Configure method, you can extract values from the IConfiguration instance into your custom type using the following code:

builder.Services.AddOptions<MyOptions>()
    .Configure<IConfiguration>((settings, configuration) =>
    {
        configuration.GetSection("MyOptions").Bind(settings);
    });

Bind を呼び出すと、プロパティ名が一致する値が構成からカスタム インスタンスにコピーされます。Calling Bind copies values that have matching property names from the configuration into the custom instance. これで IoC コンテナーで options インスタンスを関数に挿入できるようになりました。The options instance is now available in the IoC container to inject into a function.

options オブジェクトは、汎用 IOptions インターフェイスのインスタンスとして関数に挿入されます。The options object is injected into the function as an instance of the generic IOptions interface. Value プロパティを使用し、構成で見つかった値にアクセスします。Use the Value property to access the values found in your configuration.

using System;
using Microsoft.Extensions.Options;

public class HttpTrigger
{
    private readonly MyOptions _settings;

    public HttpTrigger(IOptions<MyOptions> options)
    {
        _settings = options.Value;
    }
}

オプションの使用に関する詳細については、「ASP.NET Core のオプション パターン」を参照してください。Refer to Options pattern in ASP.NET Core for more details regarding working with options.

構成ソースのカスタマイズCustomizing configuration sources

注意

構成ソースのカスタマイズは、Azure Functions ホスト バージョン 2.0.14192.0 および 3.0.14191.0 以降で使用できます。Configuration source customization is available beginning in Azure Functions host versions 2.0.14192.0 and 3.0.14191.0.

追加の構成ソースを指定するには、関数アプリの StartUp クラスの ConfigureAppConfiguration メソッドをオーバーライドします。To specify additional configuration sources, override the ConfigureAppConfiguration method in your function app's StartUp class.

次のサンプルでは、基本とオプションの環境固有のアプリ設定ファイルから、構成値を追加しています。The following sample adds configuration values from a base and an optional environment-specific app settings files.

using System.IO;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(MyNamespace.Startup))]

namespace MyNamespace
{
    public class Startup : FunctionsStartup
    {
        public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
        {
            FunctionsHostBuilderContext context = builder.GetContext();

            builder.ConfigurationBuilder
                .AddJsonFile(Path.Combine(context.ApplicationRootPath, "appsettings.json"), optional: true, reloadOnChange: false)
                .AddJsonFile(Path.Combine(context.ApplicationRootPath, $"appsettings.{context.EnvironmentName}.json"), optional: true, reloadOnChange: false)
                .AddEnvironmentVariables();
        }
    }
}

IFunctionsConfigurationBuilderConfigurationBuilder プロパティに構成プロバイダーを追加します。Add configuration providers to the ConfigurationBuilder property of IFunctionsConfigurationBuilder. 構成プロバイダーの使用の詳細については、「ASP.NET Core での構成」を参照してください。For more information on using configuration providers, see Configuration in ASP.NET Core.

FunctionsHostBuilderContextIFunctionsConfigurationBuilder.GetContext() から取得されます。A FunctionsHostBuilderContext is obtained from IFunctionsConfigurationBuilder.GetContext(). このコンテキストを使用して現在の環境名を取得し、関数アプリ フォルダー内の構成ファイルの場所を解決します。Use this context to retrieve the current environment name and resolve the location of configuration files in your function app folder.

既定では、appsettings.json などの構成ファイルは、関数アプリの出力フォルダーに自動的にコピーされません。By default, configuration files such as appsettings.json are not automatically copied to the function app's output folder. ファイルがコピーされるようにするため、次のサンプルと一致するように .csproj ファイルを更新します。Update your .csproj file to match the following sample to ensure the files are copied.

<None Update="appsettings.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>      
</None>
<None Update="appsettings.Development.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    <CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>

重要

従量課金プランまたは Premium プランで実行されている関数アプリの場合、トリガーで使用される構成値を変更すると、スケーリング エラーが発生する可能性があります。For function apps running in the Consumption or Premium plans, modifications to configuration values used in triggers can cause scaling errors. FunctionsStartup クラスによってこれらのプロパティに変更が加えられると、関数アプリのスタートアップ エラーが発生します。Any changes to these properties by the FunctionsStartup class results in a function app startup error.

次のステップNext steps

詳細については、次のリソースを参照してください。For more information, see the following resources: