Använda beroendeinmatning i .NET Azure Functions

Azure Functions stöder designmönstret för beroendeinjektion (DI), vilket är en teknik för att uppnå IoC (Inversion of Control) mellan klasser och deras beroenden.

  • Beroendeinjektion i Azure Functions bygger på funktionerna i .NET Core Dependency Injection. Vi rekommenderar att du är bekant med .NET Core-beroendeinjektion. Det finns skillnader i hur du åsidosätter beroenden och hur konfigurationsvärden läses Azure Functions i förbrukningsplanen.

  • Stöd för beroendeinjektion börjar med Azure Functions 2.x.

  • Beroendeinjektionsmönster varierar beroende på om dina C#-funktioner körs i process eller inte.

Viktigt

Vägledningen i den här artikeln gäller endast för C#-klassbiblioteksfunktioner, som körs i processen med körningen. Den här anpassade beroendeinjektionsmodellen gäller inte för isolerade .NET-funktioner,som gör att du kan köra .NET 5.0-funktioner utanför processen. Den isolerade .NET-processmodellen förlitar sig på regelbundna ASP.NET Core-beroendeinjektionsmönster. Mer information finns i Dependency injection (Beroendeinjektion) i guiden för isolerad .NET-process.

Förutsättningar

Innan du kan använda beroendeinjektion måste du installera följande NuGet-paket:

Registrera tjänster

Om du vill registrera tjänster skapar du en metod för att konfigurera och lägga till komponenter i en IFunctionsHostBuilder instans. Den Azure Functions värden skapar en instans av IFunctionsHostBuilder och skickar den direkt till din -metod.

Registrera metoden genom att lägga till FunctionsStartup sammansättningsattributet som anger det typnamn som användes vid start.

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

I det här exemplet används det Microsoft.Extensions.Http-paket som krävs för att registrera HttpClient en vid start.

Varningar

En serie registreringssteg körs före och efter körningen bearbetar startklassen. Tänk därför på följande:

  • Startklassen är endast avsedd för installation och registrering. Undvik att använda tjänster som registrerats vid start under startprocessen. Försök till exempel inte att logga ett meddelande i en loggare som registreras under start. Den här punkten i registreringsprocessen är för tidig för att dina tjänster ska vara tillgängliga för användning. När Configure metoden har körts fortsätter Functions-körningen att registrera ytterligare beroenden, vilket kan påverka hur dina tjänster fungerar.

  • Containern för beroendeinjektion innehåller endast explicit registrerade typer. De enda tjänster som är tillgängliga som injicerbara typer är de som konfigureras i Configure metoden . Därför är Functions-specifika typer som och inte tillgängliga under BindingContext ExecutionContext installationen eller som injicerbara typer.

Använda inmatade beroenden

Konstruktorinjektion används för att göra dina beroenden tillgängliga i en funktion. Användningen av konstruktorinjektion kräver att du inte använder statiska klasser för inmatade tjänster eller för dina funktionsklasser.

Följande exempel visar hur beroendena IMyService och HttpClient matas in i en HTTP-utlöst funktion.

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.");
        }
    }
}

I det här exemplet används det Microsoft.Extensions.Http-paket som krävs för att registrera HttpClient en vid start.

Tjänstens livslängd

Azure Functions-appar ger samma livslängd för tjänsten som ASP.NET Dependency Injection. För en Functions-app fungerar de olika tjänstlivslängderna på följande sätt:

  • Tillfälliga: Tillfälliga tjänster skapas vid varje lösning av tjänsten.
  • Begränsad: Den begränsade livslängden för tjänsten matchar en funktionskörningslivslängd. Begränsade tjänster skapas en gång per funktionskörning. Senare begäranden för tjänsten under körningen återanvänder den befintliga tjänstinstansen.
  • Singleton: Singleton-tjänstens livslängd matchar värdlivslängden och återanvänds vid funktionskörningar på den instansen. Singleton-livslängdstjänster rekommenderas för anslutningar och klienter, DocumentClient till exempel HttpClient instanser.

Visa eller ladda ned ett exempel på olika livslängder för tjänster på GitHub.

Loggningstjänster

Om du behöver en egen loggningsprovider registrerar du en anpassad typ som en instans av , som är tillgänglig via ILoggerProvider NuGet-paketet Microsoft.Extensions.Logging.Abstractions.

Application Insights läggs till av Azure Functions automatiskt.

Varning

  • Lägg inte till AddApplicationInsightsTelemetry() i tjänstesamlingen, som registrerar tjänster som står i konflikt med tjänster som tillhandahålls av miljön.
  • Registrera inte din egen TelemetryConfiguration eller om du använder den TelemetryClient inbyggda Application Insights funktionen. Om du behöver konfigurera din egen instans skapar du en via den som matas in enligt loggningsanpassad TelemetryClient TelemetryConfiguration telemetri i C#-funktioner.

ILogger och ILoggerFactory

Värden matar in - ILogger<T> och ILoggerFactory -tjänster i konstruktorer. Som standard filtreras dessa nya loggningsfilter dock bort från funktionsloggarna. Du måste ändra filen host.json för att välja ytterligare filter och kategorier.

Följande exempel visar hur du lägger till en ILogger<HttpTrigger> med loggar som exponeras för värden.

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.");

            // ...
    }
}

Följande exempelfil host.json lägger till loggfiltret.

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

Mer information om loggnivåer finns i Konfigurera loggnivåer.

Tjänster som tillhandahålls av funktionsappen

Funktionsvärden registrerar många tjänster. Följande tjänster är säkra att ta som ett beroende i ditt program:

Typ av tjänst Livstid Beskrivning
Microsoft.Extensions.Configuration.IConfiguration Singleton Körningskonfiguration
Microsoft.Azure.WebJobs.Host.Executors.IHostIdProvider Singleton Ansvarar för att ange värdinstansens ID

Om det finns andra tjänster som du vill ha ett beroende på skapar du ett ärende och föreslår dem på GitHub.

Åsidosätta värdtjänster

Åsidosättning av tjänster som tillhandahålls av värden stöds inte för närvarande. Om det finns tjänster som du vill åsidosätta skapar du ett ärende och föreslår dem på GitHub.

Arbeta med alternativ och inställningar

Värden som definierats i appinställningarna är tillgängliga IConfiguration i en instans, vilket gör att du kan läsa appinställningsvärden i startklassen.

Du kan extrahera värden från IConfiguration instansen till en anpassad typ. Genom att kopiera appinställningsvärdena till en anpassad typ kan du enkelt testa dina tjänster genom att göra dessa värden injicerbara. Inställningarna som läses in i konfigurationsinstansen måste vara enkla nyckel/värde-par.

Tänk på följande klass som innehåller en egenskap med namnet consistent with an app setting (Konsekvent med en appinställning):

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

Och en local.settings.json fil som kan strukturera den anpassade inställningen på följande sätt:

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

Inifrån metoden Startup.Configure kan du extrahera värden från IConfiguration instansen till din anpassade typ med hjälp av följande kod:

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

Anrop Bind kopierar värden som har matchande egenskapsnamn från konfigurationen till den anpassade instansen. Alternativinstansen är nu tillgänglig i IoC-containern för att mata in den i en funktion.

Options-objektet matas in i funktionen som en instans av det allmänna IOptions gränssnittet. Använd egenskapen Value för att komma åt värdena som finns i konfigurationen.

using System;
using Microsoft.Extensions.Options;

public class HttpTrigger
{
    private readonly MyOptions _settings;

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

Se Alternativmönster i ASP.NET Core för mer information om hur du arbetar med alternativ.

Använda ASP.NET Core-användarhemligheter

När du utvecklar lokalt ASP.NET Core ett Secret Manager-verktyg som gör att du kan lagra hemlig information utanför projektroten. Det gör det mindre troligt att hemligheter av misstag har utförts i källkontroll. Azure Functions Core Tools (version 3.0.3233 eller senare) läser automatiskt hemligheter som skapats av ASP.NET Core Secret Manager.

Om du vill konfigurera ett .NET Azure Functions-projekt att använda användarhemligheter kör du följande kommando i projektroten.

dotnet user-secrets init

Använd sedan kommandot dotnet user-secrets set för att skapa eller uppdatera hemligheter.

dotnet user-secrets set MySecret "my secret value"

Om du vill komma åt värden för användarhemligheter i funktionsappens kod använder IConfiguration du eller IOptions .

Anpassa konfigurationskällor

Anteckning

Anpassning av konfigurationskälla är tillgänglig från och Azure Functions värdversionerna 2.0.14192.0 och 3.0.14191.0.

Om du vill ange ytterligare konfigurationskällor ConfigureAppConfiguration åsidosätter du metoden i funktionsappens StartUp -klass.

Följande exempel lägger till konfigurationsvärden från en bas och en valfri miljöspecifik appinställningsfil.

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

Lägg till konfigurationsproviders ConfigurationBuilder i egenskapen för IFunctionsConfigurationBuilder . Mer information om hur du använder konfigurationsproviders finns i Konfiguration i ASP.NET Core.

En FunctionsHostBuilderContext hämtas från IFunctionsConfigurationBuilder.GetContext() . Använd den här kontexten för att hämta det aktuella miljönamnet och matcha platsen för konfigurationsfilerna i mappen för funktionsappen.

Som standard kopieras inte konfigurationsfiler som appsettings.jspå automatiskt till funktionsappens utdatamapp. Uppdatera .csproj-filen så att den matchar följande exempel för att säkerställa att filerna kopieras.

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

Viktigt

För funktionsappar som körs i förbruknings- eller Premium-planerna kan ändringar av konfigurationsvärden som används i utlösare orsaka skalningsfel. Om de här egenskaperna ändras av klassen FunctionsStartup resulterar det i ett fel vid start av funktionsappen.

Nästa steg

Mer information finns i följande resurser: