Представьте сценарий. Платёжный сервис ушёл в прод. Конфиг собран наспех, API-ключ не тот, URL без HTTPS. Всё тихо до первой реальной транзакции. Потом звонок в ночь, инцидент, откат.
Паттерн Options с валидацией на старте решает именно эту проблему.
Вместо того чтобы читать конфиг в рантайме и падать где попало, мы проверяем всё один раз при запуске. Если что-то не так, то приложение не поднимается вообще. Это лучше, чем ловить NPE или невалидный URL в середине бизнес-логики.
Шаг первый. Описываем класс опций с атрибутами валидации:
public sealed class PaymentGatewayOptions
{
[Required(ErrorMessage = "API Key is required - check your key")]
[StringLength(100, MinimumLength = 20)]
public string ApiKey { get; set; } = string.Empty;
[Required]
[Range(1, 10, ErrorMessage = "Retry count must be between 1 and 10")]
public int MaxRetries { get; set; } = 3;
[Required]
[RegularExpression(@"^https://", ErrorMessage = "Base URL must use HTTPS")]
public string BaseUrl { get; set; } = string.Empty;
[Required]
public TimeSpan Timeout { get; set; } = TimeSpan.FromSeconds(30);
}
Шаг второй. Регистрируем в Program.cs с вызовом
ValidateOnStart():builder.Services.AddOptions<PaymentGatewayOptions>()
.BindConfiguration("PaymentGateway")
.ValidateDataAnnotations()
.ValidateOnStart(); // упадёт при старте, если конфиг невалиден
Шаг третий. Используем в сервисе через
IOptions<T>:public class PaymentService
{
private readonly PaymentGatewayOptions _options;
public PaymentService(IOptions<PaymentGatewayOptions> options)
{
_options = options.Value;
}
public async Task ProcessPaymentAsync(decimal amount)
{
using var client = new HttpClient
{
BaseAddress = new Uri(_options.BaseUrl),
Timeout = _options.Timeout
};
client.DefaultRequestHeaders.Add("X-API-Key", _options.ApiKey);
for (int i = 0; i < _options.MaxRetries; i++)
{
try { /* логика запроса */ }
catch { if (i == _options.MaxRetries - 1) throw; }
}
}
}
Паттерн не новый, но cтоит использовать везде, где конфиг критичен для работы сервиса.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#sharp_view