Injeção de dependência com o SDK do Azure para .NET
Este artigo demonstra como registrar clientes de serviço do Azure das bibliotecas de cliente mais recentes do Azure para .NET para injeção de dependência em um aplicativo .NET. Cada aplicativo .NET moderno é iniciado usando as instruções fornecidas em um arquivo Program.cs .
Instalar pacotes
Para registrar e configurar clientes de serviço a partir de um Azure.
pacote prefixado:
Instale o pacote Microsoft.Extensions.Azure em seu projeto:
dotnet add package Microsoft.Extensions.Azure
Instale o pacote Azure.Identity para configurar um
TokenCredential
tipo a ser usado para autenticar todos os clientes registrados que aceitam esse tipo:dotnet add package Azure.Identity
Para fins de demonstração, o código de exemplo neste artigo usa as bibliotecas Key Vault Secrets, Blob Storage, Service Bus e Azure OpenAI. Instale os seguintes pacotes para acompanhar:
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
Registar clientes e subclientes
Um cliente de serviço é o ponto de entrada para a API de um serviço do Azure – a partir dele, os usuários da biblioteca podem invocar todas as operações que o serviço fornece e podem implementar facilmente os cenários mais comuns. Onde simplificará o design de uma API, grupos de chamadas de serviço podem ser organizados em torno de tipos de subclientes menores. Por exemplo, ServiceBusClient
pode registrar subclientes adicionais ServiceBusSender
para publicar mensagens ou ServiceBusReceiver
subclientes para consumir mensagens.
No arquivo Program.cs, invoque o AddAzureClients método extension para registrar um cliente para cada serviço. Os exemplos de código a seguir fornecem orientação sobre construtores de aplicativos dos Microsoft.AspNetCore.Builder
namespaces e 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;
}
No código anterior:
- Os clientes Key Vault Secrets, Blob Storage e Service Bus são registrados usando o AddSecretClient, AddBlobServiceClient e AddServiceBusClientWithNamespace, respectivamente. Os
Uri
argumentos - estring
-typed são passados. Para evitar especificar esses URLs explicitamente, consulte a seção Configuração da loja separadamente do código . - DefaultAzureCredential é usado para satisfazer o requisito de
TokenCredential
argumento para cada cliente registrado. Quando um dos clientes é criado,DefaultAzureCredential
é usado para autenticar. - Os subclientes do Barramento de Serviço são registrados para cada fila no serviço usando o subcliente e os tipos de opções correspondentes. Os nomes de fila para os subclientes são recuperados usando um método separado fora do registro de serviço porque o
GetQueuesAsync
método deve ser executado de forma assíncrona. - Um cliente OpenAI do Azure é registrado usando uma fábrica de cliente personalizada por meio do AddClient método, que fornece controle sobre como uma instância de cliente é criada. As fábricas de clientes personalizados são úteis nos seguintes casos:
- Você precisa usar outras dependências durante a construção do cliente.
- Não existe um método de extensão de registro para o cliente de serviço que você deseja registrar.
Utilize os clientes registados
Com os clientes registrados, conforme descrito na seção Registrar clientes e subclientes , agora você pode usá-los. No exemplo a seguir, a injeção do construtor é usada para obter o cliente de armazenamento de Blob e uma fábrica para subclientes de remetente do Service Bus em um controlador de API ASP.NET Core:
[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();
}
}
Armazene a configuração separadamente do código
Na seção Registrar clientes e subclientes, você passou explicitamente as Uri
variáveis -typed para os construtores de cliente. Essa abordagem pode causar problemas quando você executa código em ambientes diferentes durante o desenvolvimento e a produção. A equipe do .NET sugere armazenar essas configurações em arquivos JSON dependentes do ambiente. Por exemplo, você pode ter um appsettings. Development.json arquivo contendo as configurações do ambiente de desenvolvimento. Outra appsettings. Production.json arquivo conteria configurações de ambiente de produção e assim por diante. O formato do ficheiro é:
{
"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"
}
}
Você pode adicionar quaisquer propriedades da ClientOptions classe no arquivo JSON. As configurações no arquivo de configuração JSON podem ser recuperadas usando 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"));
});
No exemplo JSON anterior:
- Os nomes de chave de nível superior,
AzureDefaults
, ,KeyVault
ServiceBus
, eStorage
, são arbitrários. Todos os outros nomes de chave têm significância e a serialização JSON é executada de maneira que não diferencia maiúsculas de minúsculas. - O
AzureDefaults.Retry
objeto literal:- Representa as definições de configuração da política de nova tentativa.
- Corresponde ao Retry imóvel. Dentro desse objeto literal, você encontra a
MaxRetries
chave, que corresponde à MaxRetries propriedade.
- Os
KeyVault:VaultUri
valores ,ServiceBus:Namespace
, eStorage:ServiceUri
chave são mapeados para osUri
argumentos - estring
-typed das sobrecargas , Azure.Security.KeyVault.Secrets.SecretClient.SecretClient(Uri, TokenCredential, SecretClientOptions)Azure.Messaging.ServiceBus.ServiceBusClient.ServiceBusClient(String), e Azure.Storage.Blobs.BlobServiceClient.BlobServiceClient(Uri, TokenCredential, BlobClientOptions) construtor, respectivamente. AsTokenCredential
variantes dos construtores são usadas porque um padrãoTokenCredential
é definido através da chamada de Microsoft.Extensions.Azure.AzureClientFactoryBuilder.UseCredential(TokenCredential) método.
Configurar vários clientes de serviço com nomes diferentes
Imagine que você tem duas contas de armazenamento: uma para informações privadas e outra para informações públicas. Seu aplicativo transfere dados da conta de armazenamento pública para a privada após alguma operação. Você precisa ter dois clientes de serviço de armazenamento. Para diferenciar esses dois clientes, use o WithName método de extensão:
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddBlobServiceClient(
builder.Configuration.GetSection("PublicStorage"));
clientBuilder.AddBlobServiceClient(
builder.Configuration.GetSection("PrivateStorage"))
.WithName("PrivateStorage");
});
Usando um controlador ASP.NET Core como exemplo, acesse o cliente de serviço nomeado usando a IAzureClientFactory<TClient> interface:
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");
}
}
O cliente de serviço sem nome ainda está disponível da mesma forma que antes. Os clientes nomeados são aditivos.
Configurar uma nova política de repetição
Em algum momento, talvez você queira alterar as configurações padrão de um cliente de serviço. Por exemplo, você pode querer configurações de repetição diferentes ou usar uma versão diferente da API de serviço. Você pode definir as configurações de repetição globalmente ou por serviço. Suponha que você tenha o seguinte arquivo de appsettings.json em seu projeto ASP.NET Core:
{
"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"
}
}
Você pode alterar a política de repetição para atender às suas necessidades da seguinte forma:
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);
});
});
Você também pode colocar substituições de política de repetição no arquivo appsettings.json :
{
"KeyVault": {
"VaultUri": "https://mykeyvault.vault.azure.net",
"Retry": {
"maxRetries": 10
}
}
}
Consulte também
- Dependency injection in ASP.NET Core (Injeção de dependências no ASP.NET Core)
- Configuração em .NET
- Configuração no ASP.NET Core