أنماط Factory وOptions
استخدموا مفوّضات factory وIServiceProvider ونمط Options للتعامل مع التبعيات المشروطة أو القابلة للضبط.
أنماط Factory وOptions درس مجاني في C# Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C# Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C# Academy 4 دروس في المجموع.
عندما لا يكفي حقن الاعتماديات عبر المُنشئ
قد تحتاجون أحيانًا إلى إنشاء الخدمات بشكل مشروط استنادًا إلى بيانات وقت التشغيل، أو إلى إعدادها بطريقة مختلفة لكل حالة استخدام. وهنا تتألق أنماط المصانع ونمط Options.
مفوضات المصنع مع AddTransient
يمكنكم تمرير مفوض مصنع إلى AddTransient أو AddScoped أو AddSingleton. ويتلقى المفوض IServiceProvider، مما يتيح لكم حلّ خدمات أخرى.
builder.Services.AddTransient<IPaymentGateway>(sp =>
{
var config = sp.GetRequiredService<IOptions<PaymentConfig>>().Value;
return config.Provider == "stripe"
? new StripeGateway(config.ApiKey)
: new PayPalGateway(config.ClientId, config.Secret);
});الخيارات المُسمّاة مع IOptionsSnapshot
يربط نمط Options أقسام الإعدادات بفئات محددة الأنواع. استخدموا IOptions<T> للخدمات Singleton، وIOptionsSnapshot<T> للقيم التي تُحدَّث لكل طلب.
public class SmtpSettings
{
public string Host { get; set; } = "";
public int Port { get; set; } = 587;
public string Username { get; set; } = "";
}
// Registration
builder.Services.Configure<SmtpSettings>(
builder.Configuration.GetSection("Smtp"));
// Consumption
public class EmailService
{
private readonly SmtpSettings _settings;
public EmailService(IOptions<SmtpSettings> opts)
=> _settings = opts.Value;
}IOptionsMonitor لإعادة التحميل الفوري
توفر IOptionsMonitor<T> قيمة الخيار الحالية عند الوصول إليها، وتُخطركم عند تغير الإعدادات، مما يجعلها مناسبة جدًا لخدمات Singleton التي تحتاج إلى تحديثات مباشرة للإعدادات.
public class FeatureFlagService
{
private readonly IOptionsMonitor<FeatureFlags> _monitor;
public FeatureFlagService(IOptionsMonitor<FeatureFlags> monitor)
=> _monitor = monitor;
public bool IsEnabled(string flag)
{
// Always reads the latest config value
return _monitor.CurrentValue.Flags.GetValueOrDefault(flag);
}
}الخيارات المُسمّاة
تتيح لكم الخيارات المُسمّاة تسجيل إعدادات متعددة من النوع نفسه. استخدموا Configure<T>(name, ...)، ثم احصلوا عليها باستخدام IOptionsSnapshot<T>.Get(name).
builder.Services.Configure<S3Settings>("primary",
builder.Configuration.GetSection("S3:Primary"));
builder.Services.Configure<S3Settings>("backup",
builder.Configuration.GetSection("S3:Backup"));
public class S3Service
{
public S3Service(IOptionsSnapshot<S3Settings> opts)
{
var primary = opts.Get("primary");
var backup = opts.Get("backup");
}
}التحقق من الخيارات عند بدء التشغيل
استخدموا ValidateDataAnnotations() أو أداة تحقق مخصصة للتأكد من صحة الإعدادات قبل بدء تشغيل التطبيق. واجمعوا ذلك مع ValidateOnStart() للحصول على سلوك يفشل مبكرًا.
public class SmtpSettings
{
[Required] public string Host { get; set; } = "";
[Range(1, 65535)] public int Port { get; set; } = 587;
}
builder.Services
.AddOptions<SmtpSettings>()
.Bind(builder.Configuration.GetSection("Smtp"))
.ValidateDataAnnotations()
.ValidateOnStart();نمط المصنع المجرّد
تتيح لكم واجهة مصنع مجرّد حقن مصنع داخل الخدمات، وتأجيل الإنشاء حتى تتوفر بيانات وقت التشغيل، من دون إنشاء اعتماد مباشر على IServiceProvider.
public interface IReportFactory
{
IReport Create(string reportType);
}
public class ReportFactory : IReportFactory
{
private readonly IServiceProvider _sp;
public ReportFactory(IServiceProvider sp) => _sp = sp;
public IReport Create(string reportType) => reportType switch
{
"pdf" => _sp.GetRequiredService<PdfReport>(),
"excel"=> _sp.GetRequiredService<ExcelReport>(),
_ => throw new ArgumentException("Unknown type")
};
}
builder.Services.AddTransient<IReportFactory, ReportFactory>();الخدمات ذات المفاتيح (.NET 8)
يقدم .NET 8 الخدمات ذات المفاتيح، إذ يمكنكم تسجيل تطبيقات متعددة تحت مفاتيح مختلفة، ثم حلّ التطبيق الصحيح باستخدام [FromKeyedServices] أو GetKeyedService.
builder.Services.AddKeyedScoped<IPaymentGateway, StripeGateway>("stripe");
builder.Services.AddKeyedScoped<IPaymentGateway, PayPalGateway>("paypal");
// Resolve in a class:
public class CheckoutService(
[FromKeyedServices("stripe")] IPaymentGateway stripe,
[FromKeyedServices("paypal")] IPaymentGateway paypal) { }استخدام PostConfigure للتجاوزات
يُنفَّذ PostConfigure بعد جميع استدعاءات Configure. استخدموه لتطبيق تجاوزات في الاختبارات أو لفرض الثوابت بغض النظر عن الإعدادات التي تم تحميلها.
// In integration tests: force test values after real config
builder.Services.PostConfigure<SmtpSettings>(opts =>
{
opts.Host = "smtp.test.local";
opts.Port = 25;
});أساليب التمديد لـ IServiceCollection
اجمعوا تسجيلاتكم في أساليب تمديد للحفاظ على نظافة Program.cs وإتاحة إعادة استخدام الوحدات عبر المشاريع.
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddPaymentServices(
this IServiceCollection services,
IConfiguration config)
{
services.Configure<PaymentConfig>(config.GetSection("Payment"));
services.AddScoped<IPaymentGateway, StripeGateway>();
services.AddScoped<PaymentService>();
return services;
}
}
// Usage in Program.cs:
builder.Services.AddPaymentServices(builder.Configuration);من الواقع العملي: إشعارات متعددة الموفّرين
باستخدام مصنع وخيارات مُسمّاة معًا، يمكنكم اختيار موفّر الإشعارات المناسب في وقت التشغيل استنادًا إلى تفضيل المستخدم المخزّن في قاعدة البيانات.
builder.Services.AddKeyedScoped<INotifier, EmailNotifier>("email");
builder.Services.AddKeyedScoped<INotifier, SmsNotifier>("sms");
builder.Services.AddKeyedScoped<INotifier, PushNotifier>("push");
public class NotificationService
{
private readonly IServiceProvider _sp;
public NotificationService(IServiceProvider sp) => _sp = sp;
public Task SendAsync(string channel, string message)
{
var notifier = _sp.GetRequiredKeyedService<INotifier>(channel);
return notifier.SendAsync(message);
}
}تحقق سريع
ما الواجهة التي توفر قيمة الخيارات الحالية وتُخطِر بتغيرات الإعدادات، مما يجعلها مناسبة لخدمات Singleton؟
مراجعة: أنماط المصانع والخيارات
أهم النقاط:
- تتيح مفوضات المصنع في أساليب
Add*إنشاء الخدمات بشكل مشروط أو وفق إعدادات وقت التشغيل - يربط نمط Options أقسام الإعدادات بكائنات POCO محددة الأنواع
IOptions= ثابت، وIOptionsSnapshot= لكل طلب، وIOptionsMonitor= تحديثات مباشرة- تحققوا من صحة الخيارات عند بدء التشغيل باستخدام
ValidateDataAnnotations().ValidateOnStart() - تستبدل الخدمات ذات المفاتيح (.NET 8) الحلول البديلة القائمة على المصانع للتطبيقات المُسمّاة
الأسئلة الشائعة
هل درس «أنماط Factory وOptions» مجاني؟
نعم — نص درس «أنماط Factory وOptions» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C# Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C# Academy 4 دروس في المجموع.
ماذا ستتعلم في «أنماط Factory وOptions»؟
استخدموا مفوّضات factory وIServiceProvider ونمط Options للتعامل مع التبعيات المشروطة أو القابلة للضبط. تتمرن على C# Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ C# Academy؟
لا تُشترط خبرة سابقة. C# Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «أنماط Factory وOptions»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس C# Academy هذا؟
نعم. كل درس في C# Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- أساسيات حاوية DI
- مدد حياة الخدمات: Transient وScoped وSingleton
- الحقن عبر المُنشئ والواجهات
- أنماط Factory وOptions