【问题标题】:.Net C# + Autofac + Azure KeyVault SecretClient: 'ContainerBuilder' does not contain a definition for 'AddSecretClient'.Net C# + Autofac + Azure KeyVault SecretClient: \'ContainerBuilder\' 不包含 \'AddSecretClient\' 的定义
【发布时间】:2022-11-27 08:06:23
【问题描述】:
我正在使用 IoC 和 Autofac 在我的项目中注册依赖项,但我无法注册 SecretClient。
Autofac 配置扩展:
public static class AutofacConfigurationExtensions
{
public static void AddAutofac(this IHostBuilder builder)
{
builder.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.ConfigureContainer<ContainerBuilder>
(
(_, builder) =>
{
builder.RegisterAssemblyModules(typeof(AutofacConfigurationExtensions));
builder.RegisterModule(new SharedAutofacModule());
}
);
}
}
共享 Autofac 模块:
using Autofac;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Microsoft.Extensions.Azure;
public class SharedAutofacModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
var uri = new Uri("keyVaultUrl");
var tokenCredential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = "clientId" });
//attempt 1
builder.AddSecretClient<SecretClient>(uri).WithCredential(tokenCredential);
//attempt 2
builder.AddSecretClient<SecretClient>(_ => new(new Uri(keyVaultUrl), tokenCredential));
//attempt 3
builder.RegisterType<SecretClient>(_ => new(new Uri("keyVaultUrl"), "tokenCredential"));
builder.RegisterType<MicrosoftGraphEmailService>().As<IMailMessageSender>();
builder.RegisterType<AzureKeyVaultSecretManager>();
}
}
在我的 SharedAutofacModule 中,我可以毫无问题地注册 MicrosoftGraphEmailService 和 AzureKeyVaultSecretManager,但是我注册 SecretClient 的 3 次尝试都没有成功,它们只是无法构建。前 2 个错误如下:
“ContainerBuilder”不包含“AddSecretClient”的定义
和最好的扩展方法重载
'SecretClientBuilderExtensions.AddSecretClient(SecretClient,
Uri)'需要一个'SecretClient'类型的接收者
第三个它给出了以下错误:
方法“RegisterType”没有重载需要 1 个参数
如果我以传统的 Microsoft 方式使用 DI(如以下代码),SecretClient 的注册没有问题,但我需要使用 Autofac 来完成。
程序.cs:
var config = InitConfiguration();
var clientId = config["AzureKeyVault:ClientId"];
var keyVaultUrl = config["AzureKeyVault:KeyVaultUrl"];
if (!string.IsNullOrEmpty(clientId) && !string.IsNullOrEmpty(keyVaultUrl))
{
var tokenCredential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = clientId });
var builder = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureServices(s => s.AddSingleton<SecretClient>(_ => new(new Uri(keyVaultUrl), tokenCredential)));
builder.AddAutofac();
var host = builder.Build();
await host.RunAsync();
}
接下来我可以尝试什么?
【问题讨论】:
标签:
c#
.net
dependency-injection
inversion-of-control
autofac
【解决方案1】:
这是一个使用 EgonsoftHU.Extensions.DependencyInjection.Autofac nuget 包的例子。
我创建了一个新的 ASP.NET Core 应用程序:AzureKeyVaultSecretClientExample
AzureKeyVaultSecretClientExample.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Azure.Identity" Version="1.8.0" />
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.4.0" />
<PackageReference Include="EgonsoftHU.Extensions.DependencyInjection.Autofac" Version="2.0.0" />
</ItemGroup>
</Project>
程序.cs
using System;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using EgonsoftHU.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
builder
.Host
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>(
(hostBuilderContext, containerBuilder) =>
{
containerBuilder
// Discover all assemblies starting with the specified names.
.UseDefaultAssemblyRegistry(
nameof(AzureKeyVaultSecretClientExample),
nameof(EgonsoftHU)
)
// Enables injection for Autofac modules.
.TreatModulesAsServices()
// It will inject the IConfiguration instance
// into Autofac modules using property injection.
.RegisterModuleDependencyInstance(
hostBuilderContext.Configuration
)
// Register the EgonsoftHU Autofac module
// that will discover and register
// all other Autofac modules.
.RegisterModule<DependencyModule>();
}
);
// Add services to the container.
builder
.Services
.AddControllers()
.AddControllersAsServices();
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseAuthorization();
app.MapControllers();
app.Run();
public class AzureDependencyModule : Module
{
// It will be automatically injected.
public IConfiguration Configuration { get; set; } = default!;
protected override void Load(ContainerBuilder builder)
{
var clientId = Configuration["AzureKeyVault:ClientId"];
var keyVaultUrl = Configuration["AzureKeyVault:KeyVaultUrl"];
var tokenCredential =
new DefaultAzureCredential(
new DefaultAzureCredentialOptions()
{
ManagedIdentityClientId = clientId
}
);
// Register a factory delegate.
builder.Register<SecretClient>(
context =>
new(new Uri(keyVaultUrl), tokenCredential)
);
}
}
请注意:.RegisterModuleDependencyInstance<T>(T instance) 方法使用一个临时的、单独的 Autofac 容器专门用于 Autofac 模块。
了解更多here关于这个 nuget 包的信息。