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

أولاً

يبدو أن كل شخص لديه نسخة من هذه الشفرة، جئت لأول مرة عبر هذا النهج من & W و مؤخراً زميلي القديم (فيل هاك) نُسخته.

فقط من أجل الإكمال هذه هي الطريقة التي أفعلها بها

لماذا؟ لماذا؟

السبب هو جعل العمل مع التشكيل أسهل. في هذه اللحظة الطريقة الرئيسية تستخدم IOptions<T> وقد عقد مؤتمراً بشأن IOptionsSnapshot<T> لكن هذا قليلاً من الألم للعمل به هذا النهج يسمح لك بالعمل مع التشكيل بطريقة طبيعية أكثر. القيود هي أنه لا يمكنك استخدام IOptions<T> لن تحصل على القدرة على إعادة تحميل التشكيل دون إعادة تشغيل التطبيق. مهما كان صدقاً هذا شيء لا أريد أن أفعله أبداً

ألف - القانون

في نسختي أستخدم أعضاء الواجهة الساكنة الحديثة لأحدد أن جميع حالات هذه الفئة يجب أن تعلن Section (أ) أو الممتلكات الخاصة بها. هذا مُستخدَم إلى get قسم من تشكيل.

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

في هذه الحالة تبحث عن قسم في الإعدادات 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>();

ملاحظة: بما أن المبنِي يستطيع الوصول إلى ConfigurationManager ليس من الضروري أن يكون ذلك تمرير في.

معنى الآن لديك خيارات حول كيفية ربط التهيئة.

ميزة أخرى هي أنه إذا كنت بحاجة إلى استخدام هذه القيم لاحقاً في Program.cs ثمّ ملفّ كائن هو متوفّر لـ.

ألف - طريقة التمديد

ولتمكين كل هذا لدينا طريقة تمديد بسيطة إلى حد ما تقوم بعمل ربط التشكيل بالطبقة.

يسمح الرمز الوارد أدناه بما يلي:

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

كل هذا ممكن من قبل درجة التمديد التالية.

يمكنك أن ترى أن الدافع الرئيسي لهذا هو استخدام عناصر الواجهة الساكنة لتحديد اسم القسم. هذا مُستخدَم إلى get قسم من تشكيل.

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

©2024 Scott Galloway