أساسيات حاوية DI
افهموا عكس التحكم وتسجيل الخدمات وكيف تحل حاوية DI في .NET التبعيات.
أساسيات حاوية DI درس مجاني في C# Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C# Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C# Academy 4 دروس في المجموع.
ما هو حقن التبعيات؟
حقن التبعيات (DI) هو نمط تصميم تتلقى فيه الفئة تبعياتها من مصدر خارجي بدلًا من إنشائها بنفسها.
بدلًا من كتابة var repo = new UserRepository(); داخل الفئة، تعلن الفئة عما تحتاج إليه، وتوفره حاوية DI.
عكس التحكم
يُعد DI تطبيقًا عمليًا لمبدأ عكس التحكم (IoC): إذ يُنقل التحكم في إنشاء التبعيات من الفئة المعتمدة إلى حاوية خارجية.
وهذا يجعل اختبار الفئات واستبدالها أسهل.
إعداد حاوية DI في .NET
في تطبيق .NET، تُهيّأ حاوية DI عبر IServiceCollection في Program.cs. تُسجَّل الخدمات، ثم يحلّها وقت التشغيل.
var builder = WebApplication.CreateBuilder(args);
// Register services
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddScoped<UserService>();
var app = builder.Build();
app.Run();تعريف واجهة وتنفيذها
يعمل DI بأفضل صورة عند برمجة التطبيق اعتمادًا على الواجهات. عرّفوا واجهة تحدد عقد الخدمة، وفئة ملموسة تنفّذها.
public interface IUserRepository
{
User? GetById(int id);
}
public class UserRepository : IUserRepository
{
public User? GetById(int id)
{
// fetch from database
return new User { Id = id, Name = "Alice" };
}
}حلّ الخدمات عبر المُنشئ
تحقن الحاوية الخدمات المسجّلة تلقائيًا في المُنشئات. لا تحتاج الفئة إلا إلى التصريح بالواجهة التي تحتاج إليها، من دون الحاجة إلى الكلمة المفتاحية new.
public class UserService
{
private readonly IUserRepository _repo;
public UserService(IUserRepository repo)
{
_repo = repo;
}
public User? FindUser(int id) => _repo.GetById(id);
}تسجيل خدمات متعددة
يمكنكم تسجيل العدد الذي تحتاجون إليه من الخدمات. ومن أساليب التمديد الشائعة AddTransient وAddScoped وAddSingleton، إذ يحدد كل منها مدة حياة مختلفة.
builder.Services.AddSingleton<IConfig, AppConfig>();
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddTransient<IEmailService, SmtpEmailService>();
builder.Services.AddScoped<UserService>();استخدام IServiceProvider مباشرةً
في حالات نادرة، قد تحتاجون إلى حلّ الخدمات بطريقة إجرائية. تتيح لكم IServiceProvider استدعاء GetRequiredService<T>() لحلّ خدمة، لكن يُفضّل استخدام حقن الاعتماديات عبر المُنشئ في معظم السيناريوهات.
// Anti-pattern (service locator) — use sparingly
public class ManualResolver
{
private readonly IServiceProvider _sp;
public ManualResolver(IServiceProvider sp) => _sp = sp;
public void DoWork()
{
var svc = _sp.GetRequiredService<UserService>();
svc.FindUser(1);
}
}تسجيل الأنواع العامة المفتوحة
يدعم .NET تسجيلات الأنواع العامة المفتوحة في DI. يمكنكم تسجيل IRepository<> مرة واحدة، ثم تُحلّ إلى Repository<T> لأي نوع كيان.
builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
// Resolves as:
// IRepository<User> -> Repository<User>
// IRepository<Order> -> Repository<Order>التحقق عند بدء التشغيل
باستخدام ValidateOnStart() أو ValidateScopes = true، تستطيع الحاوية اكتشاف التسجيلات التي أُعدّت بشكل غير صحيح، مثل الاحتفاظ بخدمة Scoped داخل Singleton، عند بدء تشغيل التطبيق بدلًا من وقت التشغيل.
builder.Services.AddScoped<IMyService, MyService>();
// Detect scope violations at startup
builder.Host.UseDefaultServiceProvider(options =>
{
options.ValidateScopes = true;
options.ValidateOnBuild = true;
});تزيين الخدمات
يمكنكم إحاطة خدمة بمُزيّن من دون تعديل الفئة الأصلية. سجّلوا الخدمة الداخلية أولًا، ثم سجّلوا المُزيّن الذي يحيط بها.
builder.Services.AddScoped<IUserRepository, UserRepository>();
// Decorator pattern
builder.Services.Decorate<IUserRepository, CachedUserRepository>();
// Requires Scrutor NuGet packageمن الواقع العملي: Minimal API مع DI
في Minimal API، تُحقن الخدمات مباشرةً في معاملات معالج المسار. وتحلّها الحاوية تلقائيًا.
app.MapGet("/users/{id}", (int id, UserService svc) =>
{
var user = svc.FindUser(id);
return user is null ? Results.NotFound() : Results.Ok(user);
});تحقق سريع
ما الأسلوب الذي ينبغي تفضيله للحصول على الاعتماديات في معظم الفئات؟
مراجعة: أساسيات حاوية DI
أهم النقاط:
- يعكس DI مسؤولية إنشاء الاعتماديات: فالحاوية تنشئ الكائنات بدلًا من الفئة نفسها
- سجّلوا الخدمات باستخدام AddTransient / AddScoped / AddSingleton
- حقن الاعتماديات عبر المُنشئ هو الأسلوب القياسي والمفضّل
- الأنواع العامة المفتوحة والمُزيّنات وValidateOnBuild ميزات متقدمة وقوية
تعلم C# مع معلم ذكاء اصطناعي — مجانًا
اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.
- الدورات
- 93
- الدروس
- 346
الأسئلة الشائعة
هل درس «أساسيات حاوية DI» مجاني؟
نعم — نص درس «أساسيات حاوية DI» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C# Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C# Academy 4 دروس في المجموع.
ماذا ستتعلم في «أساسيات حاوية DI»؟
افهموا عكس التحكم وتسجيل الخدمات وكيف تحل حاوية DI في .NET التبعيات. تتمرن على C# Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ C# Academy؟
لا تُشترط خبرة سابقة. C# Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «أساسيات حاوية DI»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس C# Academy هذا؟
نعم. كل درس في C# Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- أساسيات حاوية DI
- مدد حياة الخدمات: Transient وScoped وSingleton
- الحقن عبر المُنشئ والواجهات
- أنماط Factory وOptions