在调用 BuildServiceProvider 之前将 dotnet 核心依赖注入到扩展方法

dotnet core dependency injection to extension method before BuildServiceProvider is called

我有一个 dotnet core 3.1 C# XUnit 项目。

它有一个 Startup class 包含以下 Initialise 方法:

public static IServiceProvider Initialise()
    {
        var services = new ServiceCollection();
        ConfigureServices(services);
        return services.BuildServiceProvider();
    }

ConfigureServices 方法包含以下内容:

private static void ConfigureServices(IServiceCollection services)
    {
        services.AddSharedConfiguration(_metadataTokens);
        services.AddLogging();
        services.AddTransient<IStructuredLogger>(x => new StructuredLogger(x.GetRequiredService<ILogger<PortfolioActivation>>()));

        services.AddClientApi(_metadataTokens);
    }

AddClientApi 是一个扩展方法,包含以下内容:

public static void AddClientApi(this IServiceCollection services, Dictionary<string, string> metadataTokens)
{
services.AddHttpClient(
    LocalSettings.HttpClientTypes.BrewinAvaloqHttpClient, client =>
    {
        client.BaseAddress = new Uri(metadataTokens[LocalSettings.ServiceConfigurationKeys.ClientApiBaseAddress]);
        client.DefaultRequestHeaders.Add(LocalSettings.HttpHeaderKeys.CacheControl, "no-cac
    }
).AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync(new[]
{
    TimeSpan.FromSeconds(1),
    TimeSpan.FromSeconds(5),
    TimeSpan.FromSeconds(10)
},
onRetry: (outcome, timespan, retryAttempt, context) =>
{
    //compile error here because I don't have structuredLogger      
    structuredLogger.LogInfo($"Failure on http request: {outcome}. This is retry attempt:[{retryAttempt}]"); 
}
));
}

我的问题出在 onRety 块中,我想利用已添加到 ConfigureServices 方法中的 IServiceCollection 的“StructuredLogger”服务。我不确定如何,因为此时尚未调用 BuildServiceProvider 方法?

您应该能够以与此处相同的方式从 IServiceProvider 中提取您的服务:

services.AddSingleton<MyClass>();
services.AddSingleton<MyClass2>(provider => provider.GetRequiredService<MyClass>());

this GitHub issue 所述,.AddPolicyHandler() 可用于访问 IServiceProvider,方法是:

services.AddHttpClient("...")
    .AddPolicyHandler((serviceProvider, request) => HttpPolicyExtensions.HandleTransientHttpError()
    .WaitAndRetryAsync(new[]
    {
        TimeSpan.FromSeconds(1),
        TimeSpan.FromSeconds(5),
        TimeSpan.FromSeconds(10)
    },
    onRetry: (outcome, timespan, retryAttempt, context) =>
    {
        serviceProvider.GetRequiredService<IStructuredLogger>()
            .LogInfo($"Failure on http request: {outcome}. This is retry attempt:[{retryAttempt}]");
    }
));