حاوية حقن التبعية (Dependency Injection) لـ C# (.NET): دليل شامل
\n\nحقن التبعية (DI) هو أحد أنماط التصميم الأساسية في التطوير الحديث باستخدام C# و.NET. يسمح بإنشاء تطبيقات ضعيفة الارتباط، قابلة للاختبار، وسهلة الصيانة. في هذه المقالة، سنستعرض بالتفصيل ما هي حاوية حقن التبعية، وكيفية استخدامها في .NET، مع تقديم أمثلة عملية للكود.
\n\nما هو حقن التبعية؟
\n\nحقن التبعية (Dependency Injection) هو نمط يتم فيه تزويد الكائن بتبعياته من الخارج، بدلاً من أن يقوم بإنشائها بنفسه. يتيح ذلك:
\n- \n
- تقليل الترابط بين المكونات \n
- تبسيط الاختبار (إمكانية استبدال التبعيات بـ Mock) \n
- زيادة المرونة وإعادة استخدام الكود \n
- إدارة مركزية لدورة حياة الكائنات \n
ما هي حاوية DI؟
\n\nحاوية DI (أو حاوية IoC) هي مكتبة تقوم بأتمتة عملية حقن التبعيات. تتحمل مسؤولية إنشاء الكائنات وإدارة عمرها الزمني. في .NET، حاوية DI الرئيسية هي Microsoft.Extensions.DependencyInjection، المدمجة في ASP.NET Core ويمكن استخدامها في أي تطبيق .NET.
المفاهيم الأساسية لحاوية DI
\n\nتعمل حاوية DI على المفاهيم التالية:
\n- \n
- تسجيل الخدمات — عملية إضافة الأنواع وتطبيقاتها إلى الحاوية \n
- حل التبعيات — الإنشاء التلقائي للكائنات مع تبعياتها \n
- عمر الخدمات — يحدد مدة بقاء الكائن (Transient, Scoped, Singleton) \n
إعداد حاوية DI في .NET
\n\nللبدء مع حاوية DI، يجب تثبيت الحزمة Microsoft.Extensions.DependencyInjection. يمكن القيام بذلك عبر NuGet:
dotnet add package Microsoft.Extensions.DependencyInjection\n\nبعد التثبيت، يتم إنشاء مثيل من ServiceCollection، حيث يتم تسجيل جميع التبعيات:
using Microsoft.Extensions.DependencyInjection;\n\n// إنشاء مجموعة الخدمات\nvar services = new ServiceCollection();\n\n// تسجيل الخدمات\nservices.AddTransient<ILogger, ConsoleLogger>();\nservices.AddScoped<IUserRepository, UserRepository>();\nservices.AddSingleton<IConfiguration, AppConfiguration>();\n\n// بناء مزود الخدمات\nvar serviceProvider = services.BuildServiceProvider();\n\nمثال على استخدام حاوية DI
\n\nلنأخذ مثالاً واقعياً: تطبيق لإدارة المستخدمين. سننشئ واجهات وتطبيقاتها:
\n\npublic interface IUserRepository\n{\n User GetUser(int id);\n}\n\npublic interface IEmailService\n{\n void SendEmail(string to, string subject);\n}\n\npublic class UserRepository : IUserRepository\n{\n public User GetUser(int id)\n {\n // منطق الحصول على المستخدم من قاعدة البيانات\n return new User { Id = id, Name = "John Doe" };\n }\n}\n\npublic class EmailService : IEmailService\n{\n public void SendEmail(string to, string subject)\n {\n Console.WriteLine($"تم إرسال البريد الإلكتروني إلى {to}: {subject}");\n }\n}\n\nالآن سننشئ كلاس UserService الذي يستخدم هذه التبعيات:
public class UserService\n{\n private readonly IUserRepository _userRepository;\n private readonly IEmailService _emailService;\n\n public UserService(IUserRepository userRepository, IEmailService emailService)\n {\n _userRepository = userRepository;\n _emailService = emailService;\n }\n\n public void NotifyUser(int userId)\n {\n var user = _userRepository.GetUser(userId);\n _emailService.SendEmail(user.Email, "مرحباً!");\n }\n}\n\nنقوم بتسجيل كل شيء في حاوية DI