Код: Выделить всё
"MyServices": {
"MyServiceA": {
"ServiceName": "ServiceAName",
"ConsulDataCenter": "",
"Host": "http://localhost:12345"
},
"MyServiceB": {
"ServiceName": "ServiceBName",
"ConsulDataCenter": ""
}
}
Во -первых, я Создал класс, представляющий мои параметры: < /p>
Код: Выделить всё
public class MyServicesOptions : Dictionary { }
public sealed class ConsulServiceData
{
public required string ServiceName { get; init; }
public required string ConsulDataCenter { get; init; }
public string Host { get => _uri?.Host; set => _uri = new Uri(value); }
public Uri Uri { get => _uri; }
private Uri _uri;
}
Код: Выделить всё
public interface IConfigureOptionsAsync where TOptions : class
{
Task ConfigureAsync(TOptions options, CancellationToken cancellationToken = default);
}
< /code>
и класс, который реализует вышеуказанную логику конфигурации: < /p>
public class ConfigureServicesAsync : IConfigureOptionsAsync
{
protected readonly ConsulService _consulService;
private readonly ILogger _logger;
public ConfigureMyServicesAsync(ConsulService consulService, ILogger logger)
{
_consulService = consulService;
_logger = logger;
}
public virtual async Task ConfigureAsync(MyServicesOptions options, CancellationToken cancellationToken = default)
{
try
{
foreach (var (clientName, client) in options)
{
if (string.IsNullOrEmpty(client.Host))
{
var result = await _consulService.GetServiceUriAsync(client.ServiceName, null, new QueryOptions { Datacenter = client.ConsulDataCenter }, cancellationToken).ConfigureAwait(false);
if (result is null)
{
_logger.LogWarning("Could not retrieve address from consul for service {serviceName}. Reason: {error}", client.ServiceName, result.Error);
continue;
}
client.Host = result;
}
_logger.LogInformation("Address for {serviceName} - {uri}", client.ServiceName, client.Uri);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while configuring rest consul services: {exception}", ex.Message);
throw;
}
}
}
< /code>
Затем создайте размещенную службу для асинхронной конфигурации: < /p>
public class ConfigureOptionsHostedService : IHostedService where TOptions : class
{
private readonly IServiceProvider _services;
public ConfigureOptionsHostedService(IServiceProvider services)
{
_services = services;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
using var scope = _services.CreateScope();
var configurator = scope.ServiceProvider.GetRequiredService();
var options = scope.ServiceProvider.GetRequiredService();
await configurator.ConfigureAsync(options.CurrentValue, cancellationToken);
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
< /code>
Создать методы для размещенной службы для конфигурации параметров < /p>
public static IServiceCollection ConfigureOptionsAsync(this IServiceCollection services)
where TConfigureOptionsAsync : class, IConfigureOptionsAsync
where TOptions : class
{
services.AddHostedService();
services.AddScoped();
return services;
}
< /code>
и зарегистрировать все вещи < /p>
public static void AddMyServices(this IServiceCollection services, IConfiguration configuration)
{
services.Configure(configuration.GetSection("MyServices"));
services.ConfigureOptionsAsync();
}
Код: Выделить всё
services.AddHttpClient((sp, client) =>
{
var uri = sp.GetRequiredService().Value.GetValueOrDefault("ServiceA")?.Uri;
client.BaseAddress = uri;
});
services.AddHttpClient((sp, client) =>
{
var uri = sp.GetRequiredService().Value.GetValueOrDefault("ServiceB")?.Uri;
client.BaseAddress = uri;
});
< /code>
И вот вопрос. Httpclient Код: Выделить всё
var result = await _consulService.GetServiceUriAsync(client.ServiceName, null, new QueryOptions { Datacenter = client.ConsulDataCenter }, cancellationToken).ConfigureAwait(false);
Так что же у меня Я делаю не так? Почему моя конфигурация ioptions не работает, даже если я получаю правильный адрес от консула и назначаю его правильно?
Подробнее здесь: https://stackoverflow.com/questions/776 ... ng-runtime
Мобильная версия