【问题标题】:.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&lt;T&gt;(T instance) 方法使用一个临时的、单独的 Autofac 容器专门用于 Autofac 模块。

    了解更多here关于这个 nuget 包的信息。

    【讨论】:

      猜你喜欢
      • 2021-09-08
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 2019-01-26
      • 1970-01-01
      • 1970-01-01
      • 2023-04-11
      相关资源
      最近更新 更多