在调用 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}]");
}
));
我有一个 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}]");
}
));