Använda beroendeinmatning i .NET Azure Functions
Azure Functions stöder designmönstret för beroendeinmatning (DI), vilket är en teknik för att uppnå inversion av kontroll (IoC) mellan klasser och deras beroenden.
Beroendeinmatning i Azure Functions bygger på .NET Core Dependency Injection-funktionerna. Förtrogenhet med .NET Core-beroendeinmatning rekommenderas. Det finns skillnader i hur du åsidosätter beroenden och hur konfigurationsvärden läse med Azure Functions i förbrukningsplanen.
Stöd för beroendeinmatning börjar med Azure Functions 2.x.
Beroendeinmatningsmönster varierar beroende på om C#-funktionerna körs i processen 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 beroendeinmatningsmodellen gäller inte för .NET-isolerade funktioner, vilket gör att du kan köra .NET-funktioner utan process. Den isolerade .NET-arbetsprocessmodellen förlitar sig på vanliga ASP.NET Core-beroendeinmatningsmönster. Mer information finns i Beroendeinmatning i processguiden för isolerad .NET-arbetsprocess.
Förutsättningar
Innan du kan använda beroendeinmatning måste du installera följande NuGet-paket:
Microsoft.NET.Sdk.Functions-paket version 1.0.28 eller senare
Microsoft.Extensions.DependencyInjection (för närvarande stöds endast version 2.x eller senare)
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. Azure Functions-värden skapar en instans av IFunctionsHostBuilder
och skickar den direkt till din metod.
Varning
För funktionsappar som körs i förbruknings- eller Premium-abonnemangen kan ändringar av konfigurationsvärden som används i utlösare orsaka skalningsfel. Eventuella ändringar av dessa egenskaper av FunctionsStartup
klassen resulterar i ett startfel för funktionsappen.
Inmatning av IConfiguration
kan leda till oväntat beteende. Mer information om hur du lägger till konfigurationskällor finns i Anpassa konfigurationskällor.
Om du vill registrera metoden lägger du till sammansättningsattributet FunctionsStartup
som anger typnamnet 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 en HttpClient
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 logga ett meddelande i en loggning som registreras under starten. Den här punkten i registreringsprocessen är för tidig för att dina tjänster ska vara tillgängliga för användning.
Configure
När metoden har körts fortsätter Functions-körningen att registrera andra beroenden, vilket kan påverka hur dina tjänster fungerar.Containern för beroendeinmatning innehåller endast explicit registrerade typer. De enda tjänster som är tillgängliga som injicerbara typer är de som konfigureras i
Configure
metoden. Det innebär att funktionsspecifika typer somBindingContext
ochExecutionContext
inte är tillgängliga under installationen eller som injicerbara typer.Det går inte att konfigurera ASP.NET autentisering. Functions-värden konfigurerar ASP.NET autentiseringstjänster så att API:er exponeras korrekt för kärnlivscykelåtgärder. Andra konfigurationer i en anpassad
Startup
klass kan åsidosätta den här konfigurationen, vilket orsakar oavsiktliga konsekvenser. Anropbuilder.Services.AddAuthentication()
kan till exempel avbryta autentiseringen mellan portalen och värden, vilket leder till att meddelanden som Azure Functions-körning inte kan nås.
Använda inmatade beroenden
Konstruktorinmatning används för att göra dina beroenden tillgängliga i en funktion. Användning av konstruktorinmatning 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 en HttpClient
vid start.
Tjänstlivslängd
Azure Functions-appar ger samma tjänstlivslängd som ASP.NET beroendeinmatning. För en Functions-app fungerar de olika tjänstlivslängderna på följande sätt:
- Tillfälligt: Tillfälliga tjänster skapas vid varje lösning av tjänsten.
- Omfattning: Den begränsade tjänstlivslängden matchar en livslängd för funktionskörning. 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: Livslängden för singleton-tjänsten matchar värdlivslängden och återanvänds över funktionskörningar på den instansen. Singleton-livslängdstjänster rekommenderas för anslutningar och klienter, till exempel
DocumentClient
ellerHttpClient
instanser.
Visa eller ladda ned ett exempel på olika tjänstlivslängder på GitHub.
Loggningstjänster
Om du behöver en egen loggningsprovider registrerar du en anpassad typ som en instans av ILoggerProvider
, som är tillgänglig via NuGet-paketet Microsoft.Extensions.Logging.Abstractions .
Application Insights läggs till automatiskt av Azure Functions.
Varning
- Lägg inte till
AddApplicationInsightsTelemetry()
i tjänstesamlingen, som registrerar tjänster som är i konflikt med tjänster som tillhandahålls av miljön. - Registrera inte dina egna
TelemetryConfiguration
ellerTelemetryClient
om du använder den inbyggda Application Insights-funktionen. Om du behöver konfigurera din egenTelemetryClient
instans skapar du en via den inmatadeTelemetryConfiguration
som visas i Logga anpassad telemetri i C#-funktioner.
ILogger<T> och ILoggerFactory
Värden matar in ILogger<T>
och ILoggerFactory
tjänster i konstruktorer. Dessa nya loggningsfilter filtreras dock som standard bort från funktionsloggarna. Du måste ändra host.json
filen för att välja extra filter och kategorier.
I följande exempel visas 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 funktionsappar
Funktionsvärden registrerar många tjänster. Följande tjänster är säkra att ta som ett beroende i ditt program:
Tjänsttyp | Livstid | beskrivning |
---|---|---|
Microsoft.Extensions.Configuration.IConfiguration |
Singleton | Körningskonfiguration |
Microsoft.Azure.WebJobs.Host.Executors.IHostIdProvider |
Singleton | Ansvarig för att tillhandahålla ID för värdinstansen |
Om det finns andra tjänster som du vill vara beroende av skapar du ett problem och föreslår dem på GitHub.
Åsidosättande värdtjänster
Övergripande tjänster som tillhandahålls av värden stöds för närvarande inte. Om det finns tjänster som du vill åsidosätta skapar du ett problem och föreslår dem på GitHub.
Arbeta med alternativ och inställningar
Värden som definierats i appinställningar är tillgängliga i en IConfiguration
instans, vilket gör att du kan läsa appinställningars värden i startklassen.
Du kan extrahera värden från instansen IConfiguration
till en anpassad typ. Om du kopierar appinställningarnas värden till en anpassad typ kan du enkelt testa dina tjänster genom att göra dessa värden injicerbara. Inställningar läsa in konfigurationsinstansen måste vara enkla nyckel/värde-par. För funktioner som körs i en Elastic Premium-plan kan namn på programinställningar endast innehålla bokstäver, siffror (0-9
), punkter (.
), kolon (:
) och understreck (_
). Mer information finns i Överväganden för appinställningar.
Tänk på följande klass som innehåller en egenskap som heter 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 enligt följande:
{
"IsEncrypted": false,
"Values": {
"MyOptions:MyCustomSetting": "Foobar"
}
}
Inifrån Startup.Configure
metoden kan du extrahera värden från instansen IConfiguration
till din anpassade typ med hjälp av följande kod:
builder.Services.AddOptions<MyOptions>()
.Configure<IConfiguration>((settings, configuration) =>
{
configuration.GetSection("MyOptions").Bind(settings);
});
Anropar Bind
kopior som har matchande egenskapsnamn från konfigurationen till den anpassade instansen. Alternativinstansen är nu tillgänglig i IoC-containern för att mata in i en funktion.
Alternativobjektet matas in i funktionen som en instans av det allmänna IOptions
gränssnittet. Använd egenskapen Value
för att komma åt de värden 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;
}
}
Mer information finns i Alternativmönster i ASP.NET Core.
Använda ASP.NET Core-användarhemligheter
När du utvecklar din app lokalt tillhandahåller 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 oavsiktligt checkas in till källkontrollen. Azure Functions Core Tools (version 3.0.3233 eller senare) läser automatiskt hemligheter som skapats av ASP.NET Core Secret Manager.
Kör följande kommando i projektroten för att konfigurera ett .NET Azure Functions-projekt att använda användarhemligheter.
dotnet user-secrets init
Använd dotnet user-secrets set
sedan kommandot 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 du IConfiguration
eller IOptions
.
Anpassa konfigurationskällor
Om du vill ange andra konfigurationskällor åsidosätter du ConfigureAppConfiguration
metoden i funktionsappens StartUp
klass.
Följande exempel lägger till konfigurationsvärden från både grundläggande och valfria miljöspecifika appinställningarsfiler.
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)
{
}
}
Lägg till konfigurationsprovidrar i ConfigurationBuilder
egenskapen IFunctionsConfigurationBuilder
. Mer information om hur du använder konfigurationsprovidrar finns i Konfiguration i ASP.NET Core.
A 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 funktionsappmappen.
Som standard kopieras inte konfigurationsfiler som appsettings.json
automatiskt till funktionsappens utdatamapp. .csproj
Uppdatera filen så att den matchar följande exempel för att se till att filerna kopieras.
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="appsettings.Development.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
Nästa steg
Mer information finns i följande resurser: