Back to "Поширення секції налаштування"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

ASP.NET C#

Поширення секції налаштування

Friday, 27 September 2024

Введение

Здається, що кожен має версію цього коду, Я вперше натрапив на цей підхід Філіп В і нещодавно мій старий колега Фил Хак його версію.

Просто для завершення ось як я це роблю.

Чому?

Чому, щоб зробити роботу з конфігурацією легшою. На даний момент IOptions<T> і IOptionsSnapshot<T> але це трохи нелегко працювати з ним. Цей підхід дозволяє працювати з конфігурацією в більш природній спосіб Ограничення полягає в тому, що ви не можете IOptions<T> шаблон, так що ви не маєте ' не отримуєте можливості перезавантаження конфігурації без перезапускання додаткуM SK2 Однак чесно кажучи, це те, чого я майже ніколи не хочу робити.

Код

В моїй версії я використовую останні статичні члени інтерфейсу, щоб визначити, що всі instanції цієї класи повинні заявити Section property. Це використовується для отримання розділу з конфігурації

public interface IConfigSection {
    public static abstract string Section { get; }
}

Отже, для кожного втілення ви визначаєте, яку секцію це має прив 'язати до:

public class NewsletterConfig : IConfigSection
{
    public static string Section => "Newsletter";
    
    public string SchedulerServiceUrl { get; set; } = string.Empty;
    public string AppHostUrl { get; set; } = string.Empty;
}

В цьому випадку, it' шукає секцію в конфігурації, яка називається Newsletter.

  "Newsletter": {
      "SchedulerServiceUrl" : "http://localhost:5000",
        "AppHostUrl" : "https://localhost:7240"
    
  }

Тоді ми зможемо зв 'язати це з Program.cs файл як так:


var builder = WebApplication.CreateBuilder(args);
var config = builder.Configuration;
services.ConfigurePOCO<NewsletterConfig>(config);

Ми можемо також отримати цінність конфигурації в Program.cs файл як так:

var newsletterConfig = services.ConfigurePOCO<NewsletterConfig>(config);

Або навіть WebApplicationBuilder як так:

var newsletterConfig = builder.Configure<NewsletterConfig>();

Nota: Так як будівник має доступ до ConfigurationManager це не обов 'язково має проходити в

Це означає, що тепер ви маєте можливість об 'єднати config.

Інша перевага в тому, що якщо вам потрібно використовувати ці цінності пізніше Program.cs тоді об 'єкт доступний вам.

Metodа розширення

Для цього ми маємо досить просту методу розширення, яка виконує завдання прив 'язування конфігурації до класу.

Даний код дозволяє наступне:

// These get the values and bind them to the class while adding these to Singleton Scope
var newsletterConfig = services.ConfigurePOCO<NewsletterConfig>(config);
var newsletterConfig = services.ConfigurePOCO<NewsletterConfig>(configuration.GetSection(NewsletterConfig.Section));
// Or for Builder...These obviously only work for ASP.NET Core applications, take them out if you are using this in a different context.
var newsletterConfig = builder.Configure<NewsletterConfig>();
var newsletterConfig = builder.Configure<NewsletterConfig>(NewsletterConfig.Section);
// These just return a dictionary, which can be useful to get all the values in a section
var newsletterConfig = builder.GetConfigSection<NewsletterConfig>();

Все це включено наступним класом розширення.

Ви бачите, що основним стимулом цього є використання статичних членів інтерфейсу для визначення назви секції. Потім це використовується для отримання секції з конфігураціїM SK1

namespace Mostlylucid.Shared.Config;

public static class ConfigExtensions {
    public static TConfig ConfigurePOCO<TConfig>(this IServiceCollection services, IConfigurationSection configuration)
        where TConfig : class, new() {
        if (services == null) throw new ArgumentNullException(nameof(services));
        if (configuration == null) throw new ArgumentNullException(nameof(configuration));
        
        var config = new TConfig();
        configuration.Bind(config);
        services.AddSingleton(config);
        return config;
    }

    public static TConfig ConfigurePOCO<TConfig>(this IServiceCollection services, ConfigurationManager configuration)
        where TConfig : class, IConfigSection, new()
    {
        var sectionName = TConfig.Section;
        var section = configuration.GetSection(sectionName);
        return services.ConfigurePOCO<TConfig>(section);
    }
    
    public static TConfig Configure<TConfig>(this WebApplicationBuilder builder)
        where TConfig : class, IConfigSection, new() {
        var services = builder.Services;
        var configuration = builder.Configuration;
        var sectionName = TConfig.Section;
        return services.ConfigurePOCO<TConfig>(configuration.GetSection(sectionName));
    }
    

    public static TConfig GetConfig<TConfig>(this WebApplicationBuilder builder)
        where TConfig : class, IConfigSection, new() {
        var configuration = builder.Configuration;
        var sectionName = TConfig.Section;
        var section = configuration.GetSection(sectionName).Get<TConfig>();
        return section;
        
    }
    
    public static Dictionary<string, object> GetConfigSection(this IConfiguration configuration, string sectionName) {
        var section = configuration.GetSection(sectionName);
        var result = new Dictionary<string, object>();
        foreach (var child in section.GetChildren()) {
            var key = child.Key;
            var value = child.Value;
            result.Add(key, value);
        }
        
        return result;
    }
    
    public static Dictionary<string, object> GetConfigSection<TConfig>(this WebApplicationBuilder builder)
        where TConfig : class, IConfigSection, new() {
        var configuration = builder.Configuration;
        var sectionName = TConfig.Section;
        return configuration.GetConfigSection(sectionName);
    }
}

У використанні

Використовувати їх досить просто.. В будь-якому класі, де вам потрібна ця конфігурація, ви можете просто ввести її так.

public class NewsletterService(NewsletterConfig config {
 
}

На завершення

Що ж, це дуже просто, але це методика, яку я використовую в усіх своїх проектах. Це хороший спосіб працювати з конфігурацією, і я думаю, що це трохи природніше, ніж IOptions<T> шаблон.

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.