Back to "Custom-osion laajennukset"

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#

Custom-osion laajennukset

Friday, 27 September 2024

Johdanto

Näyttää siltä, että kaikilla on versio tästä koodista, olen ensin törmännyt tähän lähestymistapaan Filip W ja viime aikoina vanha kollegani Phil Haack on hänen versionsa.

Loppujen lopuksi teen sen näin.

Miksi?

Syynä on se, että kokoonpanon kanssa työskentely helpottuu. Tällä hetkellä pääministerin tapa käyttää IOptions<T> sekä IOptionsSnapshot<T> mutta tämä on vähän tuskallista työtä. Tämän lähestymistavan avulla voit työskennellä kokoonpanon kanssa luonnollisemmalla tavalla. Rajoituksena on, että et voi käyttää IOptions<T> Kaava, joten et saa kykyä ladata kokoonpanoa uudelleen ilman, että käynnistät sovelluksen uudelleen. Rehellisesti sanottuna tämä on kuitenkin asia, jota en juuri koskaan halua tehdä.

Koodi

Omassa versiossani käytän viime aikoina static Interface -jäseniä tarkentamaan, että kaikkien tämän luokan tapausten on ilmoitettava Section kiinteistöt. Tätä käytetään saamaan osio konfiguraatiosta.

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

Määrittele siis kunkin toteutuksen osalta, mihin osioon tämä on sidottava:

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

Tässä tapauksessa se etsii osiota kokoonpanosta nimeltä Newsletter.

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

Sen jälkeen voimme sitoa tämän Program.cs tiedosto näin:


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

Voimme myös saada arvoa konfiguraation Program.cs tiedosto näin:

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

Tai jopa WebApplicationBuilder kuten näin:

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

Huomautus: Koska rakentajalla on pääsy ConfigurationManager Sen ei tarvitse mennä ohi.

Sinulla on nyt vaihtoehtoja konfiguraation sitomisesta.

Toinen etu on, että jos sinun täytyy käyttää näitä arvoja myöhemmin Program.cs tiedosto, jonka jälkeen esine on käytettävissäsi.

Laajennusmenetelmä

Kaiken tämän mahdollistamiseksi meillä on melko yksinkertainen laajennusmenetelmä, joka sitoo kokoonpanon luokkaan.

Alla oleva koodi mahdollistaa seuraavat seikat:

// 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>();

Tämä kaikki on mahdollista seuraavalla laajennuskurssilla.

Voit nähdä, että tärkein sysäys tässä on käyttää staattista käyttöliittymän jäseniä tarkentamaan osion nimeä. Tätä käytetään sitten saamaan osio konfiguraatiosta.

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);
    }
}

Käytössä

Näiden käyttö on aika yksinkertaista. Missä tahansa luokassa, jossa tarvitset tätä asetusmuotoa, voit yksinkertaisesti pistää sen näin:

public class NewsletterService(NewsletterConfig config {
 
}

Johtopäätöksenä

Se on aika yksinkertaista, mutta käytän sitä kaikissa projekteissani. Se on mukava tapa työskennellä kokoonpanon kanssa, ja mielestäni se on hieman luonnollisempi kuin IOptions<T> kuvio.

logo

©2024 Scott Galloway