Bagikan melalui


Gunakan injeksi dependensi dalam Fungsi Azure .NET

Azure Functions mendukung pola desain perangkat lunak injeksi dependensi (DI), yang merupakan teknik untuk mencapai Inversion of Control (IoC) antara kelas dan dependensinya.

  • Injeksi dependensi pada Azure Functions didasarkan pada fitur injeksi dependensi .NET Core. Disarankan untuk memahami injeksi dependensi .NET Core . Ada perbedaan dalam cara Anda menggantikan dependensi dan bagaimana nilai konfigurasi dibaca menggunakan Azure Functions pada paket Konsumsi.

  • Dukungan untuk injeksi dependensi dimulai dengan Azure Functions 2.x.

  • Pola injeksi dependensi berbeda tergantung pada apakah fungsi C# Anda berjalan dalam proses atau diluar proses.

Penting

Panduan dalam artikel ini hanya berlaku untuk fungsi pustaka kelas C#, yang berjalan dalam proses dengan runtime. Model injeksi dependensi kustom ini tidak berlaku untuk fungsi terisolasi .NET, yang memungkinkan Anda menjalankan fungsi .NET di luar proses. Model proses pekerja terisolasi .NET bergantung pada pola injeksi dependensi ASP.NET Core yang teratur. Untuk mempelajari lebih lanjut, lihat panduan proses pekerja terisolasi di .NET pada bagian Injeksi dependensi.

Prasyarat

Sebelum dapat menggunakan injeksi dependensi, Anda harus menginstal paket NuGet berikut:

Mendaftarkan layanan

Untuk mendaftarkan layanan, buat metode untuk mengonfigurasi dan menambahkan komponen ke IFunctionsHostBuilder instans. Host Azure Functions membuat instans IFunctionsHostBuilder dan meneruskannya langsung ke metode Anda.

Peringatan

Untuk aplikasi fungsi yang berjalan dalam paket Konsumsi atau Premium, modifikasi pada nilai konfigurasi yang digunakan dalam pemicu dapat menyebabkan kesalahan penskalaan. Setiap perubahan pada properti ini oleh kelas FunctionsStartup menghasilkan kesalahan pengaktifan aplikasi fungsi tersebut.

Injeksi IConfiguration dapat menyebabkan perilaku tak terduga. Untuk mempelajari selengkapnya tentang menambahkan sumber konfigurasi, lihat Menyesuaikan sumber konfigurasi.

Untuk mendaftarkan metode, tambahkan atribut assembly FunctionsStartup yang menentukan nama jenis yang digunakan selama 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>();
    }
}

Contoh ini menggunakan paket Microsoft.Extensions.Http yang diperlukan untuk mendaftar HttpClient saat startup.

Catatan Penting

Serangkaian proses pendaftaran berjalan sebelum dan sesudah runtime memproses kelas startup. Oleh karena itu, ingatlah item berikut:

  • Kelas startup dimaksudkan hanya untuk pengaturan dan pendaftaran. Hindari menggunakan layanan yang terdaftar saat startup selama proses startup. Misalnya, jangan mencoba mencatat pesan di perekam log yang sedang didaftarkan selama proses memulai. Titik proses pendaftaran ini terlalu dini agar layanan Anda tersedia untuk digunakan. Configure Setelah metode dijalankan, runtime Functions terus mendaftarkan dependensi lain, yang dapat memengaruhi cara layanan Anda beroperasi.

  • Kontainer injeksi dependensi hanya menyimpan jenis terdaftar secara eksplisit. Layanan yang tersedia sebagai tipe yang dapat diinjeksikan hanyalah yang disiapkan dalam metode Configure. Akibatnya, jenis khusus Functions seperti BindingContext dan ExecutionContext tidak tersedia selama penyiapan atau sebagai jenis yang dapat diinjeksikan.

  • Mengonfigurasi autentikasi ASP.NET tidak didukung. Host Functions mengonfigurasi layanan autentikasi ASP.NET untuk mengekspos API dengan benar untuk operasi siklus hidup inti. Konfigurasi lain di kelas kustom Startup dapat mengambil alih konfigurasi ini, menyebabkan konsekuensi yang tidak diinginkan. Misalnya, panggilan builder.Services.AddAuthentication() dapat memutuskan autentikasi antara portal dan host, yang mengarah ke pesan seperti runtime Azure Functions tidak dapat dijangkau.

Gunakan dependensi yang disuntikkan

Injeksi konstruktor digunakan untuk menjadikan dependensi Anda dapat diakses dalam fungsi. Penggunaan injeksi konstruktor mengharuskan Anda tidak menggunakan kelas statis untuk layanan yang disuntikkan atau untuk kelas fungsi Anda.

Sampel berikut menunjukkan bagaimana dependensi IMyService dan HttpClient disuntikkan ke dalam fungsi yang dipicu HTTP.

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

Contoh ini menggunakan paket Microsoft.Extensions.Http yang diperlukan untuk mendaftar HttpClient saat startup.

Masa pakai layanan

Aplikasi Azure Functions menyediakan masa pakai layanan yang sama dengan ASP.NET Injeksi Dependensi. Untuk aplikasi Functions, masa pakai layanan yang berbeda berulah sebagai berikut:

  • Sementara: Layanan sementara dibuat pada setiap resolusi layanan.
  • Terlingkup: Masa pakai layanan terlingkup cocok dengan masa pakai eksekusi fungsi. Layanan dengan ruang lingkup tertentu dibuat sekali per eksekusi fungsi. Permintaan selanjutnya untuk layanan tersebut selama pelaksanaan menggunakan ulang instance layanan yang sudah ada.
  • Singleton: Masa pakai layanan singleton cocok dengan masa pakai host dan digunakan kembali di seluruh eksekusi fungsi pada instans tersebut. Layanan seumur hidup Singleton direkomendasikan untuk koneksi dan klien, misalnya DocumentClient atau HttpClient instans.

Lihat atau unduh sampel masa pakai layanan yang berbeda di GitHub.

Layanan pengelogan

Jika Anda memerlukan penyedia log Anda sendiri, daftarkan tipe kustom sebagai instance ILoggerProvider, yang tersedia melalui paket NuGet Microsoft.Extensions.Logging.Abstractions.

Application Insights ditambahkan oleh Azure Functions secara otomatis.

Peringatan

  • Jangan tambahkan AddApplicationInsightsTelemetry() ke koleksi layanan, karena dapat mendaftarkan layanan yang bertentangan dengan layanan yang disediakan oleh lingkungan.
  • Jangan mendaftarkan milik Anda sendiri TelemetryConfiguration atau TelemetryClient jika Anda menggunakan fungsionalitas Application Insights bawaan. Jika Anda perlu mengonfigurasi instans Anda sendiri TelemetryClient, buatlah instans menggunakan yang disuntikkan TelemetryConfiguration seperti yang ditunjukkan dalam Log telemetri kustom dalam fungsi C#.

ILogger<T> dan ILoggerFactory

Host menyuntikkan ILogger<T> dan ILoggerFactory layanan ke dalam konstruktor. Namun, secara default filter pengelogan baru ini difilter dari log fungsi. Anda perlu mengubah host.json file untuk ikut serta dalam filter dan kategori tambahan.

Contoh berikut menunjukkan cara menambahkan ILogger<HttpTrigger> dengan log yang diekspos ke 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.");

        // ...
}

Contoh host.json file berikut menambahkan filter log.

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

Untuk informasi selengkapnya tentang tingkat log, lihat Mengonfigurasi tingkat log.

Layanan yang disediakan oleh aplikasi fungsi

Host fungsi mendaftarkan banyak layanan. Layanan berikut aman untuk diambil sebagai dependensi dalam aplikasi Anda:

Jenis Layanan Seumur hidup Deskripsi
Microsoft.Extensions.Configuration.IConfiguration Singleton Konfigurasi runtime
Microsoft.Azure.WebJobs.Host.Executors.IHostIdProvider Singleton Bertanggung jawab untuk menyediakan ID dari instans host.

Jika ada layanan lain yang ingin Anda ambil dependensinya, buat masalah dan usulkan di GitHub.

Mengesampingkan layanan host

Layanan penggantian yang disediakan oleh host saat ini tidak didukung. Jika ada layanan yang ingin Anda ambil alih, buat masalah dan usulkan di GitHub.

Bekerja dengan opsi dan pengaturan

Nilai yang ditentukan dalam pengaturan aplikasi tersedia dalam IConfiguration instans, yang memungkinkan Anda membaca nilai pengaturan aplikasi di kelas startup.

Anda dapat mengekstrak nilai dari IConfiguration instans ke dalam tipe khusus. Menyalin nilai pengaturan aplikasi ke jenis kustom memudahkan pengujian layanan Anda dengan membuat nilai-nilai ini dapat disuntikan. Pengaturan yang dibaca ke dalam instans konfigurasi harus berupa pasangan kunci/nilai sederhana. Untuk fungsi yang berjalan dalam paket Elastic Premium, nama pengaturan aplikasi hanya dapat berisi huruf, angka (0-9), titik (.), titik dua (:) dan garis bawah (_). Untuk informasi selengkapnya, lihat Pertimbangan pengaturan aplikasi.

Pertimbangkan kelas berikut yang menyertakan properti bernama konsisten dengan pengaturan aplikasi:

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

Dan mungkin file local.settings.json menyusun pengaturan kustom sebagai berikut:

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

Dari dalam Startup.Configuremetode, Anda dapat mengekstrak nilai dari IConfigurationinstans ke dalam tipe kustom Anda menggunakan kode berikut:

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

Memanggil Bind menyalin nilai-nilai yang memiliki nama properti yang sesuai dari konfigurasi ke dalam instans kustom. Instans opsi sekarang tersedia dalam kontainer IoC untuk disuntikkan ke dalam fungsi.

Objek opsi disuntikkan ke dalam fungsi sebagai instans antarmuka generik IOptions . Value Gunakan properti untuk mengakses nilai yang ditemukan dalam konfigurasi Anda.

using System;
using Microsoft.Extensions.Options;

public class HttpTrigger
{
    private readonly MyOptions _settings;

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

Untuk informasi selengkapnya, lihat Pola opsi di ASP.NET Core.

Menggunakan rahasia pengguna ASP.NET Core

Saat Anda mengembangkan aplikasi secara lokal, ASP.NET Core menyediakan alat Secret Manager yang memungkinkan Anda menyimpan informasi rahasia di luar akar proyek. Ini membuatnya lebih kecil kemungkinan bahwa rahasia secara tidak sengaja diterapkan pada kontrol sumber. Azure Functions Core Tools (versi 3.0.3233 atau yang lebih baru) secara otomatis membaca rahasia yang dibuat oleh ASP.NET Core Secret Manager.

Untuk mengonfigurasi proyek .NET Azure Functions untuk menggunakan rahasia pengguna, jalankan perintah berikut di akar proyek.

dotnet user-secrets init

Kemudian gunakan dotnet user-secrets set perintah untuk membuat atau memperbarui rahasia.

dotnet user-secrets set MySecret "my secret value"

Untuk mengakses nilai rahasia pengguna dalam kode aplikasi fungsi Anda, gunakan IConfiguration atau IOptions.

Menyesuaikan sumber konfigurasi

Untuk menentukan sumber konfigurasi lain, override metode ConfigureAppConfiguration di kelas StartUp aplikasi fungsi Anda.

Sampel berikut menambahkan nilai konfigurasi dari file pengaturan aplikasi dasar dan file pengaturan aplikasi yang spesifik untuk lingkungan opsional.

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)
    {
    }
}

Tambahkan penyedia konfigurasi ke properti ConfigurationBuilder dari IFunctionsConfigurationBuilder. Untuk informasi selengkapnya tentang menggunakan penyedia konfigurasi, lihat Konfigurasi di ASP.NET Core.

Sebuah FunctionsHostBuilderContext diperoleh dari IFunctionsConfigurationBuilder.GetContext(). Gunakan konteks ini untuk mengambil nama lingkungan saat ini dan menyelesaikan lokasi file konfigurasi di folder aplikasi fungsi Anda.

Secara default, file konfigurasi seperti appsettings.json tidak disalin secara otomatis ke folder output aplikasi fungsi. Perbarui file Anda .csproj agar sesuai dengan sampel berikut untuk memastikan file disalin.

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

Langkah selanjutnya

Untuk informasi selengkapnya, lihat sumber daya berikut ini: