Afhankelijkheidsinjectie gebruiken in .NET Azure Functions

Azure Functions ondersteunt het ontwerppatroon voor afhankelijkheidsinjectie (DI), een techniek voor het bereiken van Inversion of Control (IoC) tussen klassen en hun afhankelijkheden.

  • Afhankelijkheidsinjectie in Azure Functions is gebaseerd op de functies voor afhankelijkheidsinjectie van .NET Core. Bekendheid met afhankelijkheidsinjectie van .NET Core wordt aanbevolen. Er zijn verschillen in hoe u afhankelijkheden overschrijft en hoe configuratiewaarden worden gelezen met Azure Functions in het verbruiksabonnement.

  • Ondersteuning voor afhankelijkheidsinjectie begint met Azure Functions 2.x.

  • Afhankelijkheidsinjectiepatronen verschillen, afhankelijk van of uw C#-functies in-proces of buiten proces worden uitgevoerd.

Belangrijk

De richtlijnen in dit artikel zijn alleen van toepassing op C#-klassebibliotheekfuncties die in verwerking worden uitgevoerd met de runtime. Dit aangepaste model voor afhankelijkheidsinjectie is niet van toepassing op geïsoleerde .NET-functies, waarmee u .NET-functies out-of-process kunt uitvoeren. Het .NET geïsoleerde werkprocesmodel is afhankelijk van regelmatige ASP.NET Core-afhankelijkheidsinjectiepatronen. Zie Afhankelijkheidsinjectie in de .NET-handleiding voor geïsoleerde werkprocessen voor meer informatie.

Vereisten

Voordat u afhankelijkheidsinjectie kunt gebruiken, moet u de volgende NuGet-pakketten installeren:

Services registreren

Als u services wilt registreren, maakt u een methode voor het configureren en toevoegen van onderdelen aan een IFunctionsHostBuilder exemplaar. De Azure Functions-host maakt een exemplaar van IFunctionsHostBuilder en geeft deze rechtstreeks door aan uw methode.

Waarschuwing

Voor functie-apps die worden uitgevoerd in de Verbruiks- of Premium-abonnementen, kunnen wijzigingen in configuratiewaarden die in triggers worden gebruikt, schaalfouten veroorzaken. Wijzigingen in deze eigenschappen door de FunctionsStartup klasse resulteert in een opstartfout in de functie-app.

Injectie van IConfiguration kan leiden tot onverwacht gedrag. Zie Configuratiebronnen aanpassen voor meer informatie over het toevoegen van configuratiebronnen.

Als u de methode wilt registreren, voegt u het FunctionsStartup assemblykenmerk toe dat de typenaam aangeeft die tijdens het opstarten wordt gebruikt.

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>();
    }
}

In dit voorbeeld wordt het pakket Microsoft.Extensions.Http gebruikt dat is vereist om een HttpClient bij het opstarten te registreren.

Waarschuwingen

Een reeks registratiestappen worden uitgevoerd voor en nadat de runtime de opstartklasse verwerkt. Houd daarom rekening met de volgende items:

  • De opstartklasse is alleen bedoeld voor installatie en registratie. Vermijd het gebruik van services die tijdens het opstarten zijn geregistreerd tijdens het opstarten. Probeer bijvoorbeeld geen bericht te registreren in een logboekregistratie die wordt geregistreerd tijdens het opstarten. Dit punt van het registratieproces is te vroeg voordat uw services beschikbaar zijn voor gebruik. Nadat de Configure methode is uitgevoerd, blijft de Functions-runtime andere afhankelijkheden registreren, wat van invloed kan zijn op de werking van uw services.

  • De container voor afhankelijkheidsinjectie bevat alleen expliciet geregistreerde typen. De enige services die beschikbaar zijn als injecteerbare typen, zijn de services die in de Configure methode zijn ingesteld. Hierdoor zijn functiesspecifieke typen zoals BindingContext en ExecutionContext zijn ze niet beschikbaar tijdens de installatie of als injecteerbare typen.

  • Het configureren van ASP.NET verificatie wordt niet ondersteund. De Functions-host configureert ASP.NET verificatieservices om API's goed beschikbaar te maken voor kernlevenscyclusbewerkingen. Andere configuraties in een aangepaste Startup klasse kunnen deze configuratie overschrijven, wat onbedoelde gevolgen veroorzaakt. Als u bijvoorbeeld aanroept builder.Services.AddAuthentication() , kan de verificatie tussen de portal en de host worden verbroken, waardoor berichten zoals Azure Functions-runtime onbereikbaar zijn.

Geïnjecteerde afhankelijkheden gebruiken

Constructorinjectie wordt gebruikt om uw afhankelijkheden beschikbaar te maken in een functie. Het gebruik van constructorinjectie vereist dat u geen statische klassen gebruikt voor geïnjecteerde services of voor uw functieklassen.

In het volgende voorbeeld ziet u hoe de IMyService en HttpClient afhankelijkheden worden geïnjecteerd in een door HTTP geactiveerde functie.

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(IHttpClientFactory httpClientFactory, IMyService service)
    {
        this._client = httpClientFactory.CreateClient();
        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.");
    }
}

In dit voorbeeld wordt het pakket Microsoft.Extensions.Http gebruikt dat is vereist om een HttpClient bij het opstarten te registreren.

Levensduur van de service

Azure Functions-apps bieden dezelfde levensduur van de service als ASP.NET-afhankelijkheidsinjectie. Voor een Functions-app gedragen de verschillende levensduur van de service zich als volgt:

  • Tijdelijk: tijdelijke services worden gemaakt bij elke oplossing van de service.
  • Scoped: De levensduur van de service binnen het bereik komt overeen met de levensduur van de uitvoering van een functie. Scoped services worden eenmaal per functie-uitvoering gemaakt. Latere aanvragen voor die service tijdens de uitvoering hergebruiken het bestaande service-exemplaar.
  • Singleton: De levensduur van de singleton-service komt overeen met de levensduur van de host en wordt opnieuw gebruikt voor uitvoeringen van functies op dat exemplaar. Singleton-levensduurservices worden aanbevolen voor verbindingen en clients, bijvoorbeeld DocumentClient of HttpClient exemplaren.

Bekijk of download een voorbeeld van verschillende levensduur van services op GitHub.

Services voor logboekregistratie

Als u uw eigen provider voor logboekregistratie nodig hebt, registreert u een aangepast type als exemplaar van ILoggerProvider, dat beschikbaar is via het NuGet-pakket Microsoft.Extensions.Logging.Abstractions .

Application Insights wordt automatisch toegevoegd door Azure Functions.

Waarschuwing

  • Voeg niet toe aan AddApplicationInsightsTelemetry() de servicesverzameling, waarmee services worden geregistreerd die conflicteren met services die door de omgeving worden geleverd.
  • Registreer niet uw eigen TelemetryConfiguration functionaliteit of TelemetryClient als u de ingebouwde Application Insights-functionaliteit gebruikt. Als u uw eigen TelemetryClient exemplaar wilt configureren, maakt u er een via de geïnjecteerde TelemetryConfiguration , zoals wordt weergegeven in aangepaste telemetrielogboeken in C#-functies.

ILogger<T> en ILoggerFactory

De host injecteert ILogger<T> en ILoggerFactory services in constructors. Deze nieuwe logboekregistratiefilters worden echter standaard uit de functielogboeken gefilterd. U moet het host.json bestand wijzigen om u aan te kiezen voor extra filters en categorieën.

In het volgende voorbeeld ziet u hoe u een ILogger<HttpTrigger> met logboeken toevoegt die beschikbaar zijn voor de 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.");

        // ...
}

In het volgende voorbeeldbestand host.json wordt het logboekfilter toegevoegd.

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

Zie Logboekniveaus configureren voor meer informatie over logboekniveaus.

Door de functie-app geleverde services

De functiehost registreert veel services. De volgende services zijn veilig om als een afhankelijkheid in uw toepassing op te nemen:

Servicetype Levenslang Beschrijving
Microsoft.Extensions.Configuration.IConfiguration Singleton Runtimeconfiguratie
Microsoft.Azure.WebJobs.Host.Executors.IHostIdProvider Singleton Verantwoordelijk voor het verleent van de id van het hostexemplaren

Als er andere services zijn waarop u een afhankelijkheid wilt nemen, maakt u een probleem en stelt u deze voor op GitHub.

Hostservices overschrijven

Het overschrijven van services die door de host worden geleverd, wordt momenteel niet ondersteund. Als er services zijn die u wilt overschrijven, maakt u een probleem en stelt u deze voor op GitHub.

Werken met opties en instellingen

Waarden die zijn gedefinieerd in app-instellingen zijn beschikbaar in een IConfiguration exemplaar, waarmee u app-instellingenwaarden in de opstartklasse kunt lezen.

U kunt waarden uit het IConfiguration exemplaar extraheren in een aangepast type. Als u de waarden van de app-instellingen naar een aangepast type kopieert, kunt u uw services eenvoudig testen door deze waarden in te voeren. Instellingen het configuratie-exemplaar moet eenvoudige sleutel-waardeparen zijn. Voor functies die worden uitgevoerd in een Elastic Premium-abonnement, kunnen namen van toepassingsinstellingen alleen letters, cijfers (0-9), punten (.), dubbele punten (:) en onderstrepingstekens (_) bevatten. Zie Overwegingen voor app-instellingen voor meer informatie.

Houd rekening met de volgende klasse die een eigenschap bevat die consistent is met een app-instelling:

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

En een local.settings.json bestand dat de aangepaste instelling als volgt kan structuren:

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

Vanuit de Startup.Configure methode kunt u waarden uit het IConfiguration exemplaar extraheren in uw aangepaste type met behulp van de volgende code:

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

Als u waarden aanroept Bind die overeenkomen met overeenkomende eigenschapsnamen uit de configuratie naar het aangepaste exemplaar. Het exemplaar van de opties is nu beschikbaar in de IoC-container om in een functie te injecteren.

Het optiesobject wordt als exemplaar van de algemene IOptions interface in de functie geïnjecteerd. Gebruik de Value eigenschap voor toegang tot de waarden in uw configuratie.

using System;
using Microsoft.Extensions.Options;

public class HttpTrigger
{
    private readonly MyOptions _settings;

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

Zie het patroon Opties in ASP.NET Core voor meer informatie.

ASP.NET Kerngebruikersgeheimen gebruiken

Wanneer u uw app lokaal ontwikkelt, biedt ASP.NET Core een Secret Manager-hulpprogramma waarmee u geheime informatie buiten de hoofdmap van het project kunt opslaan. Het maakt het minder waarschijnlijk dat geheimen per ongeluk worden doorgevoerd in broncodebeheer. Azure Functions Core Tools (versie 3.0.3233 of hoger) leest automatisch geheimen die zijn gemaakt door de ASP.NET Core Secret Manager.

Als u een .NET Azure Functions-project wilt configureren voor het gebruik van gebruikersgeheimen, voert u de volgende opdracht uit in de hoofdmap van het project.

dotnet user-secrets init

Gebruik vervolgens de dotnet user-secrets set opdracht om geheimen te maken of bij te werken.

dotnet user-secrets set MySecret "my secret value"

Als u toegang wilt krijgen tot waarden voor gebruikersgeheimen in de code van uw functie-app, gebruikt IConfiguration u of IOptions.

Configuratiebronnen aanpassen

Als u andere configuratiebronnen wilt opgeven, overschrijft u de methode in de ConfigureAppConfiguration klasse van StartUp uw functie-app.

In het volgende voorbeeld worden configuratiewaarden uit zowel basis- als optionele omgevingsspecifieke app-instellingenbestanden toegevoegd.

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();
    }
    
    public override void Configure(IFunctionsHostBuilder builder)
    {
    }
}

Voeg configuratieproviders toe aan de ConfigurationBuilder eigenschap van IFunctionsConfigurationBuilder. Zie Configuratie in ASP.NET Core voor meer informatie over het gebruik van configuratieproviders.

A FunctionsHostBuilderContext wordt verkregen van IFunctionsConfigurationBuilder.GetContext(). Gebruik deze context om de naam van de huidige omgeving op te halen en de locatie van configuratiebestanden in de map van uw functie-app op te lossen.

Standaard worden configuratiebestanden zoals appsettings.json niet automatisch gekopieerd naar de uitvoermap van de functie-app. Werk het .csproj bestand bij zodat het overeenkomt met het volgende voorbeeld om ervoor te zorgen dat de bestanden worden gekopieerd.

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

Volgende stappen

Voor meer informatie raadpleegt u de volgende bronnen: