0Pricing
C# Academy · درس

الخيارات محدّدة الأنواع باستخدام IOptions

اربطوا أقسام الإعداد بفئات POCO باستخدام IOptions وIOptionsSnapshot وIOptionsMonitor .

الخيارات محدّدة الأنواع باستخدام IOptions درس مجاني في C# Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C# Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C# Academy 4 دروس في المجموع.

لماذا نستخدم الخيارات المحددة الأنواع؟

تؤدي قراءة الإعدادات باستخدام IConfiguration["Key"] إلى الحصول على سلاسل نصية غير محددة النوع. ويربط نمط الخيارات أقسام الإعدادات بفئات C#، ما يوفر أمانًا أثناء الترجمة، ودعم IntelliSense، وإمكانية التحقق.

تعريف فئة خيارات

أنشئ فئة POCO عادية تتطابق أسماء خصائصها مع مفاتيح JSON. ووفقًا للعرف، أضف ثابتًا ساكنًا باسم SectionName لتحديد قسم الإعدادات.

// Configuration class
public class JwtOptions
{
    public const string SectionName = "Jwt";

    public string SecretKey { get; set; } = string.Empty;
    public string Issuer    { get; set; } = string.Empty;
    public string Audience  { get; set; } = string.Empty;
    public int    ExpiryMinutes { get; set; } = 60;
}

// appsettings.json:
{
  "Jwt": {
    "SecretKey": "my-very-secret-key",
    "Issuer": "https://myapp.com",
    "Audience": "https://myapp.com/api",
    "ExpiryMinutes": 120
  }
}

تسجيل الخيارات

استدعِ Configure<T> لربط قسم إعدادات بفئة الخيارات. ويسجّل ذلك IOptions<T> وIOptionsSnapshot<T> وIOptionsMonitor<T> في DI.

// Registration
builder.Services.Configure<JwtOptions>(
    builder.Configuration.GetSection(JwtOptions.SectionName));

// Alternative shorthand:
builder.Services
    .AddOptions<JwtOptions>()
    .BindConfiguration(JwtOptions.SectionName);

// Consuming via IOptions<T>:
public class TokenService
{
    private readonly JwtOptions _opts;

    public TokenService(IOptions<JwtOptions> opts)
        => _opts = opts.Value;

    public string CreateToken()
        => $"Issuer={_opts.Issuer}, Exp={_opts.ExpiryMinutes}m";
}

IOptions مقابل IOptionsSnapshot مقابل IOptionsMonitor

توجد ثلاثة أنواع تختلف في دورات حياتها وسلوك إعادة التحميل. اختر النوع المناسب لحالة الاستخدام لديك.

// IOptions<T> — Singleton, reads config ONCE at startup
public class ApiClient(IOptions<ApiOptions> opts)
{
    private readonly ApiOptions _opts = opts.Value; // never changes
}

// IOptionsSnapshot<T> — Scoped, reloads per request
public class ReportService(IOptionsSnapshot<ReportOptions> opts)
{
    private readonly ReportOptions _opts = opts.Value; // fresh per request
}

// IOptionsMonitor<T> — Singleton, live updates + change notifications
public class FeatureService(IOptionsMonitor<FeatureFlags> monitor)
{
    public bool IsEnabled(string feature)
        => monitor.CurrentValue.EnabledFeatures.Contains(feature);
}

التحقق من صحة الخيارات باستخدام السمات

أضف سمات System.ComponentModel.DataAnnotations إلى خصائص الخيارات، ثم استدعِ ValidateDataAnnotations() لإيقاف التشغيل فورًا عند بدء التطبيق إذا كانت الإعدادات غير صالحة.

using System.ComponentModel.DataAnnotations;

public class SmtpOptions
{
    [Required]
    public string Host { get; set; } = string.Empty;

    [Range(1, 65535)]
    public int Port { get; set; } = 587;

    [Required, EmailAddress]
    public string FromAddress { get; set; } = string.Empty;
}

// Register with validation:
builder.Services
    .AddOptions<SmtpOptions>()
    .BindConfiguration("Smtp")
    .ValidateDataAnnotations()
    .ValidateOnStart(); // fail at startup, not first use

التحقق المخصص باستخدام IValidateOptions

بالنسبة إلى القواعد المعقدة التي تشمل عدة خصائص، نفّذ IValidateOptions<T> لتوفير منطق تحقق برمجي كامل.

public class JwtOptionsValidator : IValidateOptions<JwtOptions>
{
    public ValidateOptionsResult Validate(string? name, JwtOptions opts)
    {
        var errors = new List<string>();

        if (string.IsNullOrWhiteSpace(opts.SecretKey))
            errors.Add("SecretKey must not be empty");

        if (opts.SecretKey.Length < 32)
            errors.Add("SecretKey must be at least 32 characters");

        if (opts.ExpiryMinutes <= 0)
            errors.Add("ExpiryMinutes must be positive");

        return errors.Any()
            ? ValidateOptionsResult.Fail(errors)
            : ValidateOptionsResult.Success;
    }
}

builder.Services.AddSingleton<IValidateOptions<JwtOptions>, JwtOptionsValidator>();

التهيئة اللاحقة

يُنفَّذ PostConfigure بعد جميع استدعاءات Configure، ويتيح لك تجاوز القيم أو اشتقاقها — وهو مفيد للخصائص المحسوبة أو التعديلات الخاصة بالبيئة.

builder.Services.Configure<CacheOptions>(
    builder.Configuration.GetSection("Cache"));

// Override in test environment:
builder.Services.PostConfigure<CacheOptions>(opts =>
{
    if (builder.Environment.IsEnvironment("Testing"))
    {
        opts.AbsoluteExpirationMinutes = 1; // very short in tests
        opts.UseDistributedCache = false;   // use in-memory cache
    }
});

// PostConfigure always runs LAST, even after AddOptions validators

الخيارات المسماة

عندما تحتاج إلى عدة مثيلات من نوع الخيارات نفسه، مثل خادمي SMTP، استخدم الخيارات المسماة للتمييز بينها.

// Register named options:
builder.Services.Configure<SmtpOptions>("Primary",
    builder.Configuration.GetSection("Smtp:Primary"));
builder.Services.Configure<SmtpOptions>("Backup",
    builder.Configuration.GetSection("Smtp:Backup"));

// Consume with IOptionsMonitor (supports named options):
public class EmailSender
{
    private readonly SmtpOptions _primary;
    private readonly SmtpOptions _backup;

    public EmailSender(IOptionsMonitor<SmtpOptions> monitor)
    {
        _primary = monitor.Get("Primary");
        _backup  = monitor.Get("Backup");
    }
}

الاختصار BindConfiguration

تُعد السلسلة AddOptions().BindConfiguration() الطريقة الحديثة والأسلوبية لتسجيل الخيارات وربطها والتحقق منها وإيقاف التشغيل فورًا، كل ذلك في تعبير واحد.

// Full registration chain:
builder.Services
    .AddOptions<DatabaseOptions>()
    .BindConfiguration("Database")          // bind section
    .ValidateDataAnnotations()               // attribute validation
    .Validate(opts =>                        // custom rule
        opts.MaxPoolSize >= opts.MinPoolSize,
        "MaxPoolSize must be >= MinPoolSize")
    .ValidateOnStart();                      // fail at startup

// Shorthand for simple cases:
builder.Services.AddOptions<AppOptions>()
    .BindConfiguration(AppOptions.SectionName)
    .ValidateOnStart();

تطبيق عملي: خيارات أعلام الميزات

إعداد متكامل لخيارات أعلام الميزات مع دعم إعادة التحميل، ما يتيح تغيير المفاتيح في appsettings دون إعادة النشر.

public class FeatureFlags
{
    public bool EnableNewCheckout  { get; set; }
    public bool EnableAISearch     { get; set; }
    public bool EnableBetaDashboard { get; set; }
}

// appsettings.json:
// { "FeatureFlags": { "EnableNewCheckout": true, ... } }

builder.Services
    .AddOptions<FeatureFlags>()
    .BindConfiguration("FeatureFlags")
    .ValidateOnStart();

// In a controller or service:
public class CheckoutController : ControllerBase
{
    private readonly FeatureFlags _flags;

    public CheckoutController(IOptionsMonitor<FeatureFlags> m)
        => _flags = m.CurrentValue;

    [HttpGet("/checkout")]
    public IActionResult Index() =>
        _flags.EnableNewCheckout
            ? Ok("new checkout")
            : Ok("legacy checkout");
}

تحقق سريع

ما إصدار IOptions الذي ينبغي استخدامه في خدمة Singleton تحتاج إلى عكس تغييرات الإعدادات المباشرة؟

مراجعة: الخيارات المحددة الأنواع باستخدام IOptions

أهم النقاط:

  • يربط نمط الخيارات أقسام الإعدادات بكائنات POCO عبر Configure<T> أو AddOptions<T>().BindConfiguration()
  • IOptions<T>: Singleton، يقرأ مرة واحدة عند بدء التشغيل
  • IOptionsSnapshot<T>: Scoped، يعيد التحميل مع كل طلب — لا تحقنه في Singletons
  • IOptionsMonitor<T>: آمن للاستخدام مع Singleton، ويوفر CurrentValue المباشر وOnChange
  • تحقق باستخدام DataAnnotations وValidateDataAnnotations() وValidateOnStart()
  • استخدم الخيارات المسماة لعدة مثيلات من النوع نفسه

الأسئلة الشائعة

هل درس «الخيارات محدّدة الأنواع باستخدام IOptions» مجاني؟

نعم — نص درس «الخيارات محدّدة الأنواع باستخدام IOptions» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C# Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C# Academy 4 دروس في المجموع.

ماذا ستتعلم في «الخيارات محدّدة الأنواع باستخدام IOptions»؟

اربطوا أقسام الإعداد بفئات POCO باستخدام IOptions وIOptionsSnapshot وIOptionsMonitor . تتمرن على C# Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ C# Academy؟

لا تُشترط خبرة سابقة. C# Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «الخيارات محدّدة الأنواع باستخدام IOptions»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس C# Academy هذا؟

نعم. كل درس في C# Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. مصادر الإعداد وموفّروه
  2. الخيارات محدّدة الأنواع باستخدام IOptions
  3. التحقق من الخيارات والخيارات المسمّاة
  4. إدارة الأسرار
← العودة إلى C# Academy