简体   繁体   中英

dotnet core dependency injection to extension method before BuildServiceProvider is called

I have a dotnet core 3.1 C# XUnit Project.

It has a Startup class containing the following Initialise method:

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

The ConfigureServices method contains the following:

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

        services.AddClientApi(_metadataTokens);
    }

The AddClientApi is an extension method containing the following:

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}]"); 
}
));
}

My problem is in the onRety block, I'd like to make use of the "StructuredLogger" service that's been added to the IServiceCollection in the ConfigureServices method. I'm not sure how because at this point, the BuildServiceProvider method has not yet been called?

You should be able extract your service from IServiceProvider in the same fashion as you can do it here:

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

As stated in this GitHub issue , .AddPolicyHandler() can be used to get access to IServiceProvider by doing:

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}]");
    }
));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM