Bagikan melalui


Injeksi dependensi dengan Azure SDK untuk .NET

Artikel ini menunjukkan cara mendaftarkan klien layanan Azure dari pustaka klien Azure terbaru untuk .NET untuk injeksi dependensi di aplikasi .NET. Setiap aplikasi .NET modern dimulai dengan menggunakan instruksi yang disediakan dalam file Program.cs .

Memasang paket

Untuk mendaftarkan dan mengonfigurasi klien layanan dari Azure.paket -prefiks:

  1. Instal paket Microsoft.Extensions.Azure di proyek Anda:

    dotnet add package Microsoft.Extensions.Azure
    
  2. Instal paket Azure.Identity untuk mengonfigurasi jenis yang TokenCredential akan digunakan untuk mengautentikasi semua klien terdaftar yang menerima jenis seperti itu:

    dotnet add package Azure.Identity
    

Untuk tujuan demonstrasi, kode sampel dalam artikel ini menggunakan pustaka Rahasia Key Vault, Blob Storage, Bus Layanan, dan Azure OpenAI. Instal paket berikut untuk diikuti:

dotnet add package Azure.Security.KeyVault.Secrets
dotnet add package Azure.Storage.Blobs
dotnet add package Azure.Messaging.ServiceBus
dotnet add package Azure.AI.OpenAI

Mendaftarkan klien dan subkelas

Klien layanan adalah titik masuk ke API untuk layanan Azure - dari itu, pengguna pustaka dapat memanggil semua operasi yang disediakan layanan dan dapat dengan mudah menerapkan skenario yang paling umum. Di mana ia akan menyederhanakan desain API, grup panggilan layanan dapat diatur di sekitar jenis subkelas yang lebih kecil. Misalnya, ServiceBusClient dapat mendaftarkan subkelas tambahan ServiceBusSender untuk menerbitkan pesan atau ServiceBusReceiver subkelas untuk menggunakan pesan.

Dalam file Program.cs, panggil AddAzureClients metode ekstensi untuk mendaftarkan klien untuk setiap layanan. Sampel kode berikut memberikan panduan tentang penyusun aplikasi dari Microsoft.AspNetCore.Builder namespace layanan dan Microsoft.Extensions.Hosting .

using Azure.Identity;
using Azure.Messaging.ServiceBus;
using Azure.Messaging.ServiceBus.Administration;
using Microsoft.Extensions.Azure;
using Azure.AI.OpenAI;

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

builder.Services.AddAzureClients(async clientBuilder =>
{
    // Register clients for each service
    clientBuilder.AddSecretClient(new Uri("<key_vault_url>"));
    clientBuilder.AddBlobServiceClient(new Uri("<storage_url>"));
    clientBuilder.AddServiceBusClientWithNamespace(
        "<your_namespace>.servicebus.windows.net");

    // Set a credential for all clients to use by default
    DefaultAzureCredential credential = new();
    clientBuilder.UseCredential(credential);

    // Register a subclient for each Service Bus Queue
    List<string> queueNames = await GetQueueNames(credential);
    foreach (string queue in queueNames)
    {
        clientBuilder.AddClient<ServiceBusSender, ServiceBusClientOptions>(
            (_, _, provider) => provider.GetService<ServiceBusClient>()
                .CreateSender(queue)).WithName(queue);
    }

    // Register a custom client factory
    clientBuilder.AddClient<AzureOpenAIClient, AzureOpenAIClientOptions>(
        (options, _, _) => new AzureOpenAIClient(
            new Uri("<url_here>"), credential, options)); 
});

WebApplication app = builder.Build();

async Task<List<string>> GetQueueNames(DefaultAzureCredential credential)
{
    // Query the available queues for the Service Bus namespace.
    var adminClient = new ServiceBusAdministrationClient
        ("<your_namespace>.servicebus.windows.net", credential);
    var queueNames = new List<string>();

    // Because the result is async, the queue names need to be captured
    // to a standard list to avoid async calls when registering. Failure to
    // do so results in an error with the services collection.
    await foreach (QueueProperties queue in adminClient.GetQueuesAsync())
    {
        queueNames.Add(queue.Name);
    }

    return queueNames;
}

Dalam kode sebelumnya:

  • Rahasia Key Vault, Blob Storage, dan klien Bus Layanan didaftarkan menggunakan AddSecretClient, AddBlobServiceClient dan AddServiceBusClientWithNamespace, masing-masing. Argumen Uri- dan string-typed diteruskan. Untuk menghindari menentukan URL ini secara eksplisit, lihat bagian Simpan konfigurasi secara terpisah dari kode .
  • DefaultAzureCredential digunakan untuk memenuhi TokenCredential persyaratan argumen untuk setiap klien terdaftar. Ketika salah satu klien dibuat, DefaultAzureCredential digunakan untuk mengautentikasi.
  • Bus Layanan subkelas didaftarkan untuk setiap antrean pada layanan menggunakan jenis opsi subkelas dan yang sesuai. Nama antrean untuk subkelas diambil menggunakan metode terpisah di luar pendaftaran layanan karena GetQueuesAsync metode harus dijalankan secara asinkron.
  • Klien Azure OpenAI terdaftar menggunakan pabrik klien kustom melalui AddClient metode , yang memberikan kontrol atas cara instans klien dibuat. Pabrik klien kustom berguna dalam kasus berikut:
    • Anda perlu menggunakan dependensi lain selama konstruksi klien.
    • Metode ekstensi pendaftaran tidak ada untuk klien layanan yang ingin Anda daftarkan.

Menggunakan klien terdaftar

Dengan klien yang terdaftar, seperti yang dijelaskan di bagian Daftarkan klien dan subkelas , Anda sekarang dapat menggunakannya. Dalam contoh berikut, injeksi konstruktor digunakan untuk mendapatkan klien Blob Storage dan pabrik untuk subkelas pengirim Bus Layanan dalam pengontrol API Inti ASP.NET:

[ApiController]
[Route("[controller]")]
public class MyApiController : ControllerBase
{
    private readonly BlobServiceClient _blobServiceClient;
    private readonly ServiceBusSender _serviceBusSender;
  
    public MyApiController(
        BlobServiceClient blobServiceClient,
        IAzureClientFactory<ServiceBusSender> senderFactory)
    {
        _blobServiceClient = blobServiceClient;
        _serviceBusSender = senderFactory.CreateClient("myQueueName");
    }
  
    [HttpGet]
    public async Task<IEnumerable<string>> Get()
    {
        BlobContainerClient containerClient = 
            _blobServiceClient.GetBlobContainerClient("demo");
        var results = new List<string>();

        await foreach (BlobItem blob in containerClient.GetBlobsAsync())
        {
            results.Add(blob.Name);
        }

        return results.ToArray();
    }
}

Menyimpan konfigurasi secara terpisah dari kode

Di bagian Daftarkan klien dan subkelas , Anda secara eksplisit meneruskan Urivariabel -typed ke konstruktor klien. Pendekatan ini dapat menyebabkan masalah ketika Anda menjalankan kode terhadap lingkungan yang berbeda selama pengembangan dan produksi. Tim .NET menyarankan penyimpanan konfigurasi tersebut dalam file JSON yang bergantung pada lingkungan. Misalnya, Anda dapat memiliki appsetting . Development.json file yang berisi pengaturan lingkungan pengembangan. Appsetting lain. Production.json file akan berisi pengaturan lingkungan produksi, dan sebagainya. Format file adalah:

{
  "AzureDefaults": {
    "Diagnostics": {
      "IsTelemetryDisabled": false,
      "IsLoggingContentEnabled": true
    },
    "Retry": {
      "MaxRetries": 3,
      "Mode": "Exponential"
    }
  },
  "KeyVault": {
    "VaultUri": "https://mykeyvault.vault.azure.net"
  },
  "ServiceBus": {
    "Namespace": "<your_namespace>.servicebus.windows.net"
  },
  "Storage": {
    "ServiceUri": "https://mydemoaccount.storage.windows.net"
  }
}

Anda dapat menambahkan properti apa pun dari ClientOptions kelas ke dalam file JSON. Pengaturan dalam file konfigurasi JSON dapat diambil menggunakan IConfiguration.

builder.Services.AddAzureClients(clientBuilder =>
{
    clientBuilder.AddSecretClient(
        builder.Configuration.GetSection("KeyVault"));

    clientBuilder.AddBlobServiceClient(
        builder.Configuration.GetSection("Storage"));

    clientBuilder.AddServiceBusClientWithNamespace(
        builder.Configuration["ServiceBus:Namespace"]);

    clientBuilder.UseCredential(new DefaultAzureCredential());

    // Set up any default settings
    clientBuilder.ConfigureDefaults(
        builder.Configuration.GetSection("AzureDefaults"));
});

Dalam sampel JSON sebelumnya:

Mengonfigurasi beberapa klien layanan dengan nama yang berbeda

Bayangkan Anda memiliki dua akun penyimpanan: satu untuk informasi privat dan satu lagi untuk informasi publik. Aplikasi Anda mentransfer data dari publik ke akun penyimpanan privat setelah beberapa operasi. Anda harus memiliki dua klien layanan penyimpanan. Untuk membedakan kedua klien tersebut WithName , gunakan metode ekstensi:

builder.Services.AddAzureClients(clientBuilder =>
{
    clientBuilder.AddBlobServiceClient(
        builder.Configuration.GetSection("PublicStorage"));

    clientBuilder.AddBlobServiceClient(
            builder.Configuration.GetSection("PrivateStorage"))
        .WithName("PrivateStorage");
});

Menggunakan pengontrol ASP.NET Core sebagai contoh, akses klien layanan bernama menggunakan IAzureClientFactory<TClient> antarmuka:

public class HomeController : Controller
{
    private readonly BlobServiceClient _publicStorage;
    private readonly BlobServiceClient _privateStorage;

    public HomeController(
        BlobServiceClient defaultClient,
        IAzureClientFactory<BlobServiceClient> clientFactory)
    {
        _publicStorage = defaultClient;
        _privateStorage = clientFactory.CreateClient("PrivateStorage");
    }
}

Klien layanan yang tidak disebutkan namanya masih tersedia dengan cara yang sama seperti sebelumnya. Klien bernama bersifat aditif.

Mengonfigurasi kebijakan coba lagi baru

Pada titik tertentu, Anda mungkin ingin mengubah pengaturan default untuk klien layanan. Misalnya, Anda mungkin menginginkan pengaturan coba lagi yang berbeda atau menggunakan versi API layanan yang berbeda. Anda dapat mengatur pengaturan coba lagi secara global atau per layanan. Asumsikan Anda memiliki file appsettings.json berikut dalam proyek ASP.NET Core Anda:

{
  "AzureDefaults": {
    "Retry": {
      "maxRetries": 3
    }
  },
  "KeyVault": {
    "VaultUri": "https://mykeyvault.vault.azure.net"
  },
  "ServiceBus": {
    "Namespace": "<your_namespace>.servicebus.windows.net"
  },
  "Storage": {
    "ServiceUri": "https://store1.storage.windows.net"
  },
  "CustomStorage": {
    "ServiceUri": "https://store2.storage.windows.net"
  }
}

Anda dapat mengubah kebijakan coba lagi agar sesuai dengan kebutuhan Anda seperti:

builder.Services.AddAzureClients(clientBuilder =>
{
    // Establish the global defaults
    clientBuilder.ConfigureDefaults(
        builder.Configuration.GetSection("AzureDefaults"));
    clientBuilder.UseCredential(new DefaultAzureCredential());

    // A Key Vault Secrets client using the global defaults
    clientBuilder.AddSecretClient(
        builder.Configuration.GetSection("KeyVault"));

    // A Blob Storage client with a custom retry policy
    clientBuilder.AddBlobServiceClient(
            builder.Configuration.GetSection("Storage"))
        .ConfigureOptions(options => options.Retry.MaxRetries = 10);

    clientBuilder.AddServiceBusClientWithNamespace(
            builder.Configuration["ServiceBus:Namespace"])
        .ConfigureOptions(options => options.RetryOptions.MaxRetries = 10);

    // A named storage client with a different custom retry policy
    clientBuilder.AddBlobServiceClient(
            builder.Configuration.GetSection("CustomStorage"))
        .WithName("CustomStorage")
        .ConfigureOptions(options =>
        {
            options.Retry.Mode = Azure.Core.RetryMode.Exponential;
            options.Retry.MaxRetries = 5;
            options.Retry.MaxDelay = TimeSpan.FromSeconds(120);
        });
});

Anda juga dapat menempatkan penimpaan kebijakan coba lagi dalam file appsettings.json :

{
  "KeyVault": {
    "VaultUri": "https://mykeyvault.vault.azure.net",
    "Retry": {
      "maxRetries": 10
    }
  }
}

Lihat juga