.NET의 옵션 패턴
옵션 패턴은 클래스를 사용하여 관련 설정 그룹에 대한 강력한 형식의 액세스를 제공합니다. 구성 설정이 시나리오에 따라 별도 클래스로 격리된 경우 앱은 두 가지 중요한 소프트웨어 엔지니어링 원칙을 따릅니다.
- ISP(Interface Segregation Principle, 인터페이스 분리 원칙) 또는 캡슐화: 구성 설정에 종속된 시나리오(클래스)는 사용하는 구성 설정에 의해서만 결정됩니다.
- 관심사의 분리 앱의 다른 부분에 대한 설정은 다른 설정에 종속되거나 연결되지 않습니다.
옵션은 구성 데이터의 유효성을 검사하는 메커니즘도 제공합니다. 자세한 내용은 옵션 유효성 검사 섹션을 참조하세요.
계층적 구성 바인딩
관련 구성 값을 읽는 기본 방법은 옵션 패턴를 사용하는 것입니다. 옵션 패턴은 제네릭 형식 매개 변수 TOptions
가 class
로 제한되는 IOptions<TOptions> 인터페이스를 통해 사용할 수 있습니다. IOptions<TOptions>
는 나중에 종속성 주입을 통해 제공할 수 있습니다. 자세한 내용은 .NET에서 종속성 주입을 참조하세요.
예를 들어, appsettings.json 파일에서 강조 표시된 구성 값을 읽으려면 다음을 수행합니다.
{
"SecretKey": "Secret key value",
"TransientFaultHandlingOptions": {
"Enabled": true,
"AutoRetryDelay": "00:00:07"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
다음 TransientFaultHandlingOptions
클래스를 만듭니다.
public sealed class TransientFaultHandlingOptions
{
public bool Enabled { get; set; }
public TimeSpan AutoRetryDelay { get; set; }
}
옵션 패턴을 사용하는 경우 옵션 클래스는
- 매개 변수가 없는 공용 생성자를 사용하는 비추상이어야 합니다.
- 바인딩할 공용 읽기/쓰기 속성을 포함합니다(필드는 바인딩되지 않음).
다음 코드는 Program.cs C# 파일의 일부이며 다음과 같습니다.
- ConfigurationBinder.Bind를 호출하여
TransientFaultHandlingOptions
클래스를"TransientFaultHandlingOptions"
섹션에 바인딩합니다. - 구성 데이터를 표시합니다.
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using ConsoleJson.Example;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Configuration.Sources.Clear();
IHostEnvironment env = builder.Environment;
builder.Configuration
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true);
TransientFaultHandlingOptions options = new();
builder.Configuration.GetSection(nameof(TransientFaultHandlingOptions))
.Bind(options);
Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");
using IHost host = builder.Build();
// Application code should start here.
await host.RunAsync();
// <Output>
// Sample output:
이전 코드에서 JSON 구성 파일에는 TransientFaultHandlingOptions
인스턴스에 바인딩된 "TransientFaultHandlingOptions"
섹션이 있습니다. 이렇게 하면 C# 개체 속성이 구성의 해당 값으로 수화됩니다.
ConfigurationBinder.Get<T>
는 지정된 형식을 바인딩하고 반환합니다. ConfigurationBinder.Get<T>
가 ConfigurationBinder.Bind
를 사용하는 것보다 편리할 수 있습니다. 다음 코드에서는 ConfigurationBinder.Get<T>
와 TransientFaultHandlingOptions
클래스를 함께 사용하는 방법을 보여 줍니다.
var options =
builder.Configuration.GetSection(nameof(TransientFaultHandlingOptions))
.Get<TransientFaultHandlingOptions>();
Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");
앞의 코드에서 ConfigurationBinder.Get<T>
는 기본 구성에서 채워진 속성 값을 사용하여 TransientFaultHandlingOptions
개체의 인스턴스를 획득하는 데 사용됩니다.
Important
ConfigurationBinder 클래스는 .Bind(object instance)
및 .Get<T>()
와 같이 class
로 제한되지 않는 여러 API를 노출합니다. 옵션 인터페이스를 사용하는 경우 앞서 언급한 옵션 클래스 제약 조건을 준수해야 합니다.
옵션 패턴을 사용하는 경우 한 가지 대체 방법은 "TransientFaultHandlingOptions"
섹션을 바인딩하고 종속성 주입 서비스 컨테이너에 추가하는 것입니다. 다음 코드에서 TransientFaultHandlingOptions
는 Configure를 통해 서비스 컨테이너에 추가되고 구성에 바인딩됩니다.
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.Configure<TransientFaultHandlingOptions>(
builder.Configuration.GetSection(
key: nameof(TransientFaultHandlingOptions)));
앞의 예에서 builder
는 HostApplicationBuilder의 인스턴스입니다.
팁
key
매개 변수는 검색할 구성 섹션의 이름입니다. 이를 표현하는 형식의 이름과 일치할 필요가 ‘없습니다’. 예를 들어 "FaultHandling"
라는 섹션이 TransientFaultHandlingOptions
클래스에 의해 표현될 수 있습니다. 이 인스턴스에서는 "FaultHandling"
을 GetSection 함수에 대신 전달합니다. nameof
연산자는 명명된 섹션이 해당하는 형식과 일치하는 경우 편의를 위해 사용됩니다.
위의 코드를 사용하여 다음 코드는 위치 옵션을 읽습니다.
using Microsoft.Extensions.Options;
namespace ConsoleJson.Example;
public sealed class ExampleService(IOptions<TransientFaultHandlingOptions> options)
{
private readonly TransientFaultHandlingOptions _options = options.Value;
public void DisplayValues()
{
Console.WriteLine($"TransientFaultHandlingOptions.Enabled={_options.Enabled}");
Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={_options.AutoRetryDelay}");
}
}
위 코드에서는 앱을 시작한 후의 JSON 구성 파일의 변경 사항을 읽지 않습니다. 앱이 시작된 후 변경 내용을 읽으려면 IOptionsSnapshot 또는 IOptionsMonitor를 사용하여 변경 내용이 발생할 때마다 모니터링하고 그에 따라 대응합니다.
옵션 인터페이스
:
:
- 범위가 지정된 수명 또는 임시 수명에서 모든 주입 확인마다 옵션을 다시 계산하는 시나리오에서 유용합니다. 자세한 내용은 IOptionsSnapshot을 사용하여 업데이트된 데이터를 참조하세요.
- 범위 지정됨으로 등록되므로 Singleton 서비스에 주입할 수 없습니다.
- 명명된 옵션을 지원합니다.
:
- 옵션을 검색하고
TOptions
인스턴스에 대한 옵션 알림을 관리하는 데 사용됩니다. - Singleton으로 등록되며 서비스 수명에 주입할 수 있습니다.
- 지원:
- 알림 변경
- 명명된 옵션
- 다시 로드할 수 있는 구성
- 선택적 옵션 무효화(IOptionsMonitorCache<TOptions>)
IOptionsFactory<TOptions>는 새로운 옵션 인스턴스를 만듭니다. 단일 Create 메서드가 있습니다. 기본 구현에서는 등록된 모든 IConfigureOptions<TOptions> 및 IPostConfigureOptions<TOptions>를 사용하며 먼저 구성을 모두 실행한 다음, 사후 구성을 수행합니다. IConfigureNamedOptions<TOptions>와 IConfigureOptions<TOptions>를 구별하며 적절한 인터페이스만 호출합니다.
IOptionsMonitorCache<TOptions>는 IOptionsMonitor<TOptions>에서 TOptions
인스턴스를 캐시하는 데 사용됩니다. IOptionsMonitorCache<TOptions>는 모니터의 옵션 인스턴스를 무효화하므로 값이 다시 계산됩니다(TryRemove). TryAdd를 사용하여 값을 수동으로 도입할 수 있습니다. 모든 명명된 인스턴스를 필요에 따라 다시 만들어야 하는 경우 Clear 메서드가 사용됩니다.
IOptionsChangeTokenSource<TOptions>는 기본 TOptions
인스턴스에 대한 변경 내용을 추적하는 IChangeToken을 가져오는 데 사용됩니다. 변경 토큰 기본 요소에 대한 자세한 내용은 변경 알림을 참조하세요.
옵션 인터페이스의 이점
제네릭 래퍼 형식을 사용하면 DI(종속성 주입) 컨테이너에서 옵션의 수명을 분리할 수 있습니다. IOptions<TOptions>.Value 인터페이스는 일반 제약 조건을 포함하여 옵션 형식에 대한 추상화 계층을 제공합니다. 이 기능은 다음과 같은 이점을 제공합니다.
T
구성 인스턴스의 평가는 IOptions<TOptions>.Value가 주입될 때가 아니라 액세스될 때로 지연됩니다. 이는T
옵션을 다양한 위치에서 사용하고T
에 대한 변경 없이 수명 의미 체계를 선택할 수 있기 때문에 중요합니다.T
형식의 옵션을 등록하는 경우T
형식을 명시적으로 등록할 필요가 없습니다. 이는 간단한 기본값을 사용하여 라이브러리를 작성하고 호출자가 특정 수명을 갖는 옵션을 DI 컨테이너에 등록하도록 강제하지 않으려는 경우에 편리합니다.- API의 관점에서 보면
T
형식에 제약 조건을 사용할 수 있습니다(이 경우T
가 참조 형식으로 제한됨).
IOptionsSnapshot을 사용하여 업데이트된 데이터 읽기
IOptionsSnapshot<TOptions>을 사용하면, 옵션은 액세스될 때 요청당 한 번씩 계산되고 요청의 수명 동안 캐시됩니다. 업데이트된 구성 값 읽기를 지원하는 구성 공급자를 사용하는 경우 앱을 시작한 후 구성 변경 내용을 읽습니다.
IOptionsMonitor
와 IOptionsSnapshot
의 차이점은 다음과 같습니다.
IOptionsMonitor
는 언제든지 현재 옵션 값을 검색하는 싱글톤 서비스로, 싱글톤 종속성에서 특히 유용합니다.IOptionsSnapshot
은 범위가 지정된 서비스이며IOptionsSnapshot<T>
개체가 생성될 때 옵션의 스냅샷을 제공합니다. 옵션 스냅숏은 임시 및 범위가 지정된 종속성과 함께 사용하도록 설계되었습니다.
다음 코드에서는 IOptionsSnapshot<TOptions> 메서드를 사용합니다.
using Microsoft.Extensions.Options;
namespace ConsoleJson.Example;
public sealed class ScopedService(IOptionsSnapshot<TransientFaultHandlingOptions> options)
{
private readonly TransientFaultHandlingOptions _options = options.Value;
public void DisplayValues()
{
Console.WriteLine($"TransientFaultHandlingOptions.Enabled={_options.Enabled}");
Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={_options.AutoRetryDelay}");
}
}
다음 코드에서는 TransientFaultHandlingOptions
가 바인딩되는 구성 인스턴스를 등록합니다.
builder.Services
.Configure<TransientFaultHandlingOptions>(
configurationRoot.GetSection(
nameof(TransientFaultHandlingOptions)));
앞의 코드에서 Configure<TOptions>
메서드는 TOptions
가 바인딩할 구성 인스턴스를 등록하고 구성이 변경될 때 옵션을 업데이트하는 데 사용됩니다.
IOptionsMonitor
IOptionsMonitor
유형은 변경 알림을 지원하며 앱이 구성 소스 변경에 동적으로 응답해야 할 수 있는 시나리오를 활성화합니다. 이 기능은 앱이 시작된 후 구성 데이터의 변경 내용에 대응해야 하는 경우에 유용합니다. 변경 알림은 다음과 같은 파일 시스템 기반 구성 공급자에 대해서만 지원됩니다.
- Microsoft.Extensions.Configuration.Ini
- Microsoft.Extensions.Configuration.Json
- Microsoft.Extensions.Configuration.KeyPerFile
- Microsoft.Extensions.Configuration.UserSecrets
- Microsoft.Extensions.Configuration.Xml
옵션 모니터를 사용하려면 구성 섹션에서 동일한 방식으로 옵션 개체를 구성해야 합니다.
builder.Services
.Configure<TransientFaultHandlingOptions>(
configurationRoot.GetSection(
nameof(TransientFaultHandlingOptions)));
다음 예제에서는 IOptionsMonitor<TOptions>를 사용합니다.
using Microsoft.Extensions.Options;
namespace ConsoleJson.Example;
public sealed class MonitorService(IOptionsMonitor<TransientFaultHandlingOptions> monitor)
{
public void DisplayValues()
{
TransientFaultHandlingOptions options = monitor.CurrentValue;
Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");
}
}
위 코드에서는 앱을 시작한 후 JSON 구성 파일 변경 사항을 읽습니다.
팁
Docker 컨테이너나 네트워크 공유 같은 일부 파일 시스템은 변경 알림을 안정적으로 전송할 수 없습니다. 이러한 환경에서 IOptionsMonitor<TOptions> 인터페이스를 사용하는 경우 DOTNET_USE_POLLING_FILE_WATCHER
환경 변수를 1
또는 true
로 설정하여 파일 시스템에서 변경 내용을 폴링합니다. 변경 내용이 폴링되는 간격은 4초마다이며 구성할 수 없습니다.
Docker 컨테이너에 대한 자세한 내용은 .NET 앱 컨테이너화를 참조하세요.
명명된 옵션은 IConfigureNamedOptions 사용을 지원
명명된 옵션:
- 여러 구성 섹션이 동일한 속성에 바인딩되는 경우에 유용합니다.
- 대/소문자를 구분합니다.
다음 appsettings.json 파일을 고려하세요.
{
"Features": {
"Personalize": {
"Enabled": true,
"ApiKey": "aGEgaGEgeW91IHRob3VnaHQgdGhhdCB3YXMgcmVhbGx5IHNvbWV0aGluZw=="
},
"WeatherStation": {
"Enabled": true,
"ApiKey": "QXJlIHlvdSBhdHRlbXB0aW5nIHRvIGhhY2sgdXM/"
}
}
}
Features:Personalize
및 Features:WeatherStation
를 바인딩하는 두 개의 클래스를 만드는 대신 각 섹션에 다음 클래스가 사용됩니다.
public class Features
{
public const string Personalize = nameof(Personalize);
public const string WeatherStation = nameof(WeatherStation);
public bool Enabled { get; set; }
public string ApiKey { get; set; }
}
다음 코드는 명명된 옵션을 구성합니다.
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
// Omitted for brevity...
builder.Services.Configure<Features>(
Features.Personalize,
builder.Configuration.GetSection("Features:Personalize"));
builder.Services.Configure<Features>(
Features.WeatherStation,
builder.Configuration.GetSection("Features:WeatherStation"));
다음 코드는 명명된 옵션을 표시합니다.
public sealed class Service
{
private readonly Features _personalizeFeature;
private readonly Features _weatherStationFeature;
public Service(IOptionsSnapshot<Features> namedOptionsAccessor)
{
_personalizeFeature = namedOptionsAccessor.Get(Features.Personalize);
_weatherStationFeature = namedOptionsAccessor.Get(Features.WeatherStation);
}
}
모든 옵션은 명명된 인스턴스입니다. IConfigureOptions<TOptions> 인스턴스는 string.Empty
인 Options.DefaultName
인스턴스를 대상으로 지정한 것처럼 처리됩니다. 또한 IConfigureNamedOptions<TOptions>는 IConfigureOptions<TOptions>를 구현합니다. IOptionsFactory<TOptions>의 기본 구현에는 각 옵션을 적절하게 사용하기 위한 논리가 있습니다. null
명명된 옵션은 특정 명명된 인스턴스 대신 모든 명명된 인스턴스를 대상으로 지정하는 데 사용됩니다. ConfigureAll 및 PostConfigureAll에서 이 규칙을 사용합니다.
OptionsBuilder API
OptionsBuilder<TOptions>는 TOptions
인스턴스를 구성하는 데 사용됩니다. OptionsBuilder
는 AddOptions<TOptions>(string optionsName)
호출에 대한 단일 매개 변수이므로 모든 후속 호출에 나타나는 대신 명명된 옵션 생성을 간소화합니다. 옵션 유효성 검사 및 서비스 종속성을 허용하는 ConfigureOptions
오버로드는 OptionsBuilder
를 통해서만 사용할 수 있습니다.
OptionsBuilder
는 옵션 유효성 검사 섹션에서 사용됩니다.
DI 서비스를 사용하여 옵션 구성
옵션을 구성할 때 종속성 주입을 사용하여 등록된 서비스에 액세스하고 이를 사용하여 옵션을 구성할 수 있습니다. 이는 옵션을 구성하기 위해 서비스에 액세스해야 할 때 유용합니다. 다음 두 가지 방법으로 옵션을 구성하는 동안 DI에서 서비스에 액세스할 수 있습니다.
구성 대리자를 OptionsBuilder<TOptions>의 Configure에 전달합니다.
OptionsBuilder<TOptions>
는 최대 5개의 서비스를 사용하여 옵션을 구성할 수 있는 Configure의 오버로드를 제공합니다.builder.Services .AddOptions<MyOptions>("optionalName") .Configure<ExampleService, ScopedService, MonitorService>( (options, es, ss, ms) => options.Property = DoSomethingWith(es, ss, ms));
IConfigureOptions<TOptions> 또는 IConfigureNamedOptions<TOptions>를 구현하는 형식을 만들고 해당 형식을 서비스로 등록합니다.
서비스 만들기가 더 복잡하므로 구성 위임을 Configure에 전달하는 것이 좋습니다. 형식을 만드는 작업은 Configure를 호출할 때 프레임워크에서 수행하는 작업에 해당합니다. Configure을 호출하면 지정된 일반 서비스 유형을 허용하는 생성자가 있는 일시적인 일반 IConfigureNamedOptions<TOptions>가 등록됩니다.
옵션 유효성 검사
옵션 유효성 검사를 통해 옵션 값의 유효성을 검사할 수 있습니다.
다음 appsettings.json 파일을 고려하세요.
{
"MyCustomSettingsSection": {
"SiteTitle": "Amazing docs from Awesome people!",
"Scale": 10,
"VerbosityLevel": 32
}
}
다음 클래스는 "MyCustomSettingsSection"
구성 섹션에 바인딩되고 몇 가지 DataAnnotations
규칙을 적용합니다.
using System.ComponentModel.DataAnnotations;
namespace ConsoleJson.Example;
public sealed class SettingsOptions
{
public const string ConfigurationSectionName = "MyCustomSettingsSection";
[Required]
[RegularExpression(@"^[a-zA-Z''-'\s]{1,40}$")]
public required string SiteTitle { get; set; }
[Required]
[Range(0, 1_000,
ErrorMessage = "Value for {0} must be between {1} and {2}.")]
public required int Scale { get; set; }
[Required]
public required int VerbosityLevel { get; set; }
}
위의 SettingsOptions
클래스에서 ConfigurationSectionName
속성에는 바인딩할 구성 섹션의 이름이 포함됩니다. 이 시나리오에서 옵션 개체는 구성 섹션의 이름을 제공합니다.
팁
구성 섹션 이름은 바인딩되는 구성 개체와 관련이 없습니다. 즉, "FooBarOptions"
라는 구성 섹션은 ZedOptions
라는 옵션 개체에 바인딩할 수 있습니다. 일반적으로 이름을 동일하게 지정할 수 있지만 반드시 그럴 필요가 ‘없으며’ 실제로 이름 충돌이 발생할 수 있습니다.
코드는 다음과 같습니다.
- AddOptions를 호출하여
SettingsOptions
클래스에 바인딩되는 OptionsBuilder<TOptions>를 가져옵니다. - ValidateDataAnnotations를 호출하여
DataAnnotations
를 사용한 유효성 검사를 사용하도록 설정합니다.
builder.Services
.AddOptions<SettingsOptions>()
.Bind(Configuration.GetSection(SettingsOptions.ConfigurationSectionName))
.ValidateDataAnnotations();
ValidateDataAnnotations
확장 메서드는 Microsoft.Extensions.Options.DataAnnotations NuGet 패키지에서 정의됩니다.
다음 코드는 구성 값을 표시하거나 유효성 검사 오류를 보고합니다.
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace ConsoleJson.Example;
public sealed class ValidationService
{
private readonly ILogger<ValidationService> _logger;
private readonly IOptions<SettingsOptions> _config;
public ValidationService(
ILogger<ValidationService> logger,
IOptions<SettingsOptions> config)
{
_config = config;
_logger = logger;
try
{
SettingsOptions options = _config.Value;
}
catch (OptionsValidationException ex)
{
foreach (string failure in ex.Failures)
{
_logger.LogError("Validation error: {FailureMessage}", failure);
}
}
}
}
다음 코드는 대리자를 사용하여 보다 복잡한 유효성 검사 규칙을 적용합니다.
builder.Services
.AddOptions<SettingsOptions>()
.Bind(Configuration.GetSection(SettingsOptions.ConfigurationSectionName))
.ValidateDataAnnotations()
.Validate(config =>
{
if (config.Scale != 0)
{
return config.VerbosityLevel > config.Scale;
}
return true;
}, "VerbosityLevel must be > than Scale.");
유효성 검사는 런타임 시 발생하지만 대신 ValidateOnStart
에 대한 호출을 연결하여 시작 시 발생하도록 구성할 수 있습니다.
builder.Services
.AddOptions<SettingsOptions>()
.Bind(Configuration.GetSection(SettingsOptions.ConfigurationSectionName))
.ValidateDataAnnotations()
.Validate(config =>
{
if (config.Scale != 0)
{
return config.VerbosityLevel > config.Scale;
}
return true;
}, "VerbosityLevel must be > than Scale.")
.ValidateOnStart();
.NET 8부터 시작 시 특정 옵션 형식에 대한 유효성 검사를 사용하도록 설정하는 대체 API인 AddOptionsWithValidateOnStart<TOptions>(IServiceCollection, String)을 사용할 수 있습니다.
builder.Services
.AddOptionsWithValidateOnStart<SettingsOptions>()
.Bind(Configuration.GetSection(SettingsOptions.ConfigurationSectionName))
.ValidateDataAnnotations()
.Validate(config =>
{
if (config.Scale != 0)
{
return config.VerbosityLevel > config.Scale;
}
return true;
}, "VerbosityLevel must be > than Scale.");
복잡한 유효성 검사의 경우 IValidateOptions
다음 클래스는 IValidateOptions<TOptions>를 구현합니다.
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
namespace ConsoleJson.Example;
sealed partial class ValidateSettingsOptions(
IConfiguration config)
: IValidateOptions<SettingsOptions>
{
public SettingsOptions? Settings { get; private set; } =
config.GetSection(SettingsOptions.ConfigurationSectionName)
.Get<SettingsOptions>();
public ValidateOptionsResult Validate(string? name, SettingsOptions options)
{
StringBuilder? failure = null;
if (!ValidationRegex().IsMatch(options.SiteTitle))
{
(failure ??= new()).AppendLine($"{options.SiteTitle} doesn't match RegEx");
}
if (options.Scale is < 0 or > 1_000)
{
(failure ??= new()).AppendLine($"{options.Scale} isn't within Range 0 - 1000");
}
if (Settings is { Scale: 0 } && Settings.VerbosityLevel <= Settings.Scale)
{
(failure ??= new()).AppendLine("VerbosityLevel must be > than Scale.");
}
return failure is not null
? ValidateOptionsResult.Fail(failure.ToString())
: ValidateOptionsResult.Success;
}
[GeneratedRegex("^[a-zA-Z''-'\\s]{1,40}$")]
private static partial Regex ValidationRegex();
}
IValidateOptions
를 사용하면 유효성 검사 코드를 클래스로 이동할 수 있습니다.
참고 항목
이 예제 코드는 Microsoft.Extensions.Configuration.Json NuGet 패키지를 사용합니다.
이전 코드를 사용하면 다음 코드로 서비스를 구성할 때 유효성 검사가 사용하도록 설정됩니다.
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
// Omitted for brevity...
builder.Services.Configure<SettingsOptions>(
builder.Configuration.GetSection(
SettingsOptions.ConfigurationSectionName));
builder.Services.TryAddEnumerable(
ServiceDescriptor.Singleton
<IValidateOptions<SettingsOptions>, ValidateSettingsOptions>());
옵션 사후 구성
IPostConfigureOptions<TOptions>를 사용하여 사후 구성을 설정합니다. 사후 구성은 모든 IConfigureOptions<TOptions> 구성이 발생한 후에 실행되며, 구성을 재정의해야 하는 시나리오에서 유용할 수 있습니다.
builder.Services.PostConfigure<CustomOptions>(customOptions =>
{
customOptions.Option1 = "post_configured_option1_value";
});
PostConfigure를 사용하여 명명된 옵션을 사후 구성할 수 있습니다.
builder.Services.PostConfigure<CustomOptions>("named_options_1", customOptions =>
{
customOptions.Option1 = "post_configured_option1_value";
});
모든 구성 인스턴스를 사후 구성하려면 PostConfigureAll을 사용합니다.
builder.Services.PostConfigureAll<CustomOptions>(customOptions =>
{
customOptions.Option1 = "post_configured_option1_value";
});
참고 항목
.NET