.NET에서 사용자 지정 구성 공급자 구현
JSON, XML 및 INI 파일과 같은 일반적인 구성 소스에 사용할 수 있는 여러 구성 공급자가 있습니다. 사용 가능한 공급자 중 하나가 애플리케이션 요구 사항에 맞지 않는 경우 사용자 지정 구성 공급자를 구현해야 할 수 있습니다. 이 문서에서는 데이터베이스를 구성 소스로 사용하는 사용자 지정 구성 공급자를 구현하는 방법을 알아봅니다.
사용자 지정 구성 공급자
샘플 앱에서는 EF(Entity Framework) Core를 사용하여 데이터베이스에서 구성 키-값 쌍을 읽는 기본 구성 공급자를 만드는 방법을 보여 줍니다.
이 공급자의 특징은 다음과 같습니다.
- 데모용으로 EF 메모리 내 데이터베이스를 사용합니다.
- 연결 문자열이 필요한 데이터베이스를 사용하려면 임시 구성에서 연결 문자열을 가져옵니다.
- 이 공급자는 시작 시 데이터베이스 테이블을 구성으로 읽어 들입니다. 이 공급자는 키별 기준으로 데이터베이스를 쿼리하지 않습니다.
- 변경 시 다시 로드가 구현되지 않으므로 앱이 시작된 후 데이터베이스를 업데이트해도 앱 구성에 영향을 주지 않습니다.
데이터베이스에 구성 값을 저장하는 Settings
레코드 형식 엔터티를 정의합니다. 예를 들어 Models 폴더에 Settings.cs 파일을 추가할 수 있습니다.
namespace CustomProvider.Example.Models;
public record Settings(string Id, string? Value);
레코드 형식에 관한 자세한 내용은 C#의 레코드 형식를 참조하세요.
구성된 값을 저장 및 액세스하는 EntityConfigurationContext
를 추가합니다.
Providers/EntityConfigurationContext.cs:
using CustomProvider.Example.Models;
using Microsoft.EntityFrameworkCore;
namespace CustomProvider.Example.Providers;
public sealed class EntityConfigurationContext(string? connectionString) : DbContext
{
public DbSet<Settings> Settings => Set<Settings>();
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
_ = connectionString switch
{
{ Length: > 0 } => optionsBuilder.UseSqlServer(connectionString),
_ => optionsBuilder.UseInMemoryDatabase("InMemoryDatabase")
};
}
}
OnConfiguring(DbContextOptionsBuilder)을 재정의하여 적절한 데이터베이스 연결을 사용할 수 있습니다. 예를 들어 연결 문자열이 제공된 경우 SQL Server에 연결할 수 있습니다. 그러지 않으면 메모리 내 데이터베이스를 사용할 수 있습니다.
IConfigurationSource를 구현하는 클래스를 만듭니다.
Providers/EntityConfigurationSource.cs:
using Microsoft.Extensions.Configuration;
namespace CustomProvider.Example.Providers;
public sealed class EntityConfigurationSource(
string? connectionString) : IConfigurationSource
{
public IConfigurationProvider Build(IConfigurationBuilder builder) =>
new EntityConfigurationProvider(connectionString);
}
ConfigurationProvider에서 상속하여 사용자 지정 구성 공급자를 만듭니다. 구성 공급자는 비어 있는 데이터베이스를 초기화합니다. 구성 키는 대/소문자를 구분하지 않으므로 데이터베이스를 초기화하는 데 사용되는 사전은 대/소문자를 구분하지 않는 비교자(StringComparer.OrdinalIgnoreCase)를 사용하여 생성됩니다.
Providers/EntityConfigurationProvider.cs:
using CustomProvider.Example.Models;
using Microsoft.Extensions.Configuration;
namespace CustomProvider.Example.Providers;
public sealed class EntityConfigurationProvider(
string? connectionString)
: ConfigurationProvider
{
public override void Load()
{
using var dbContext = new EntityConfigurationContext(connectionString);
dbContext.Database.EnsureCreated();
Data = dbContext.Settings.Any()
? dbContext.Settings.ToDictionary(
static c => c.Id,
static c => c.Value, StringComparer.OrdinalIgnoreCase)
: CreateAndSaveDefaultValues(dbContext);
}
static Dictionary<string, string?> CreateAndSaveDefaultValues(
EntityConfigurationContext context)
{
var settings = new Dictionary<string, string?>(
StringComparer.OrdinalIgnoreCase)
{
["WidgetOptions:EndpointId"] = "b3da3c4c-9c4e-4411-bc4d-609e2dcc5c67",
["WidgetOptions:DisplayLabel"] = "Widgets Incorporated, LLC.",
["WidgetOptions:WidgetRoute"] = "api/widgets"
};
context.Settings.AddRange(
[.. settings.Select(static kvp => new Settings(kvp.Key, kvp.Value))]);
context.SaveChanges();
return settings;
}
}
AddEntityConfiguration
확장 메서드를 사용하여 구성 소스를 기본 ConfigurationManager
인스턴스에 추가할 수 있습니다.
Extensions/ConfigurationManagerExtensions.cs:
using CustomProvider.Example.Providers;
namespace Microsoft.Extensions.Configuration;
public static class ConfigurationManagerExtensions
{
public static ConfigurationManager AddEntityConfiguration(
this ConfigurationManager manager)
{
var connectionString = manager.GetConnectionString("WidgetConnectionString");
IConfigurationBuilder configBuilder = manager;
configBuilder.Add(new EntityConfigurationSource(connectionString));
return manager;
}
}
ConfigurationManager는 IConfigurationBuilder 및 IConfigurationRoot 모두의 구현이므로 확장 메서드는 연결 문자열 구성에 액세스하고 EntityConfigurationSource
를 추가할 수 있습니다.
다음 코드는 Program.cs에서 사용자 지정 EntityConfigurationProvider
를 사용하는 방법을 보여 줍니다.
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using CustomProvider.Example;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Configuration.AddEntityConfiguration();
builder.Services.Configure<WidgetOptions>(
builder.Configuration.GetSection("WidgetOptions"));
using IHost host = builder.Build();
WidgetOptions options = host.Services.GetRequiredService<IOptions<WidgetOptions>>().Value;
Console.WriteLine($"DisplayLabel={options.DisplayLabel}");
Console.WriteLine($"EndpointId={options.EndpointId}");
Console.WriteLine($"WidgetRoute={options.WidgetRoute}");
await host.RunAsync();
// Sample output:
// WidgetRoute=api/widgets
// EndpointId=b3da3c4c-9c4e-4411-bc4d-609e2dcc5c67
// DisplayLabel=Widgets Incorporated, LLC.
공급자 사용
사용자 지정 구성 공급자를 사용하려면 옵션 패턴을 사용하면 됩니다. 샘플 앱이 준비되면 옵션 개체를 정의하여 위젯 설정을 나타냅니다.
namespace CustomProvider.Example;
public class WidgetOptions
{
public required Guid EndpointId { get; set; }
public required string DisplayLabel { get; set; } = null!;
public required string WidgetRoute { get; set; } = null!;
}
Configure에 대한 호출은 TOptions
가 바인딩하는 구성 인스턴스를 등록합니다.
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using CustomProvider.Example;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Configuration.AddEntityConfiguration();
builder.Services.Configure<WidgetOptions>(
builder.Configuration.GetSection("WidgetOptions"));
using IHost host = builder.Build();
WidgetOptions options = host.Services.GetRequiredService<IOptions<WidgetOptions>>().Value;
Console.WriteLine($"DisplayLabel={options.DisplayLabel}");
Console.WriteLine($"EndpointId={options.EndpointId}");
Console.WriteLine($"WidgetRoute={options.WidgetRoute}");
await host.RunAsync();
// Sample output:
// WidgetRoute=api/widgets
// EndpointId=b3da3c4c-9c4e-4411-bc4d-609e2dcc5c67
// DisplayLabel=Widgets Incorporated, LLC.
위 코드는 구성의 "WidgetOptions"
섹션에서 WidgetOptions
개체를 구성합니다. 그러면 EF 설정의 종속성 주입 준비 IOptions<WidgetOptions>
표현을 노출하는 옵션 패턴을 사용할 수 있습니다. 이 옵션은 궁극적으로 사용자 지정 구성 공급자에서 제공됩니다.
참고 항목
.NET