دليل inversify الكامل لـ TypeScript: أمثلة وتطبيقات عملية

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

ما هو Inversify ولماذا تحتاجه؟

Inversify هي حاوية IoC (عكس التحكم) قوية وخفيفة الوزن مخصصة لـ TypeScript و JavaScript. تطبق نمط حقن التبعيات (Dependency Injection)، وهو أحد المبادئ الأساسية لـ SOLID. تساعدك Inversify في إدارة التبعيات بين الكلاسات، مما يجعل الكود أكثر نمطية، قابلية للاختبار، وسهولة في الصيانة.

لماذا تحتاج هذا؟ في البرمجة التقليدية، الكلاسات تنشئ تبعياتها بنفسها (مثلاً باستخدام new). هذا يؤدي إلى ارتباط قوي بين مكونات الكود. Inversify تعكس هذه العملية: التبعيات "تُحقن" من الخارج (ومن هنا جاء اسم عكس التحكم). الحاوية تتولى إنشاء وإدارة دورة حياة الكائنات.

المزايا الرئيسية لاستخدام Inversify:

  • ارتباط ضعيف: الكلاسات تعتمد على التجريدات (الواجهات) وليس على التطبيقات الملموسة.
  • اختبار سهل: يمكنك بسهولة استبدال التبعيات الحقيقية بـ mocks/stubs أثناء الاختبارات.
  • إدارة دورة الحياة: الحاوية يمكنها إنشاء كائنات كـ singletons أو إنشاء نسخ جديدة في كل مرة.
  • قراءة وصيانة أفضل: جميع التبعيات مُعلنة بوضوح ويسهل تتبعها.
  • قابلية التوسع: مثالية للمشاريع الكبيرة التي تحتوي على العديد من الوحدات.

تثبيت Inversify

يتم تثبيت Inversify عبر npm. للعمل مع TypeScript، ستحتاج أيضاً إلى تثبيت reflect-metadata (مكتبة للعمل مع الديكورات) وتهيئة ملف tsconfig.json.

# تثبيت Inversify و reflect-metadata
npm install inversify reflect-metadata --save

# تثبيت أنواع TypeScript (إذا لم تكن مثبتة)
npm install @types/node --save-dev

تهيئة tsconfig.json:

{
  "compilerOptions": {
    "target": "ES6",
    "module": "commonjs",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "types": ["reflect-metadata"]
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

ملاحظة مهمة: الديكورات @injectable() و @inject() تعمل فقط عند تفعيل experimentalDecorators و emitDecoratorMetadata.

بداية سريعة مع مثال برمجي

لننشئ مثالاً بسيطاً: خدمة لإرسال الإشعارات. سيكون لدينا واجهة INotificationService، وتطبيقها EmailNotificationService، وكلاس UserService الذي يستخدم هذه الخدمة.

// 1. استيراد الوحدات المطلوبة
import "reflect-metadata";
import { Container, injectable, inject } from "inversify";

// 2. تعريف الواجهة (التجريد)
interface INotificationService {
  send(message: string): void;
}

// 3. تطبيق الواجهة
@injectable()
class EmailNotificationService implements INotificationService {
  send(message: string): void {
    console.log(`إرسال بريد إلكتروني: ${message}`);
  }
}

// 4. كلاس يعتمد على INotificationService
@injectable()
class UserService {
  private notificationService: INotificationService;

  constructor(
    @inject("INotificationService") notificationService: INotificationService
  ) {
    this.notificationService = notificationService;
  }

  notifyUser(userId: string): void {
    this.notificationService.send(`إشعار للمستخدم ${userId}`);
  }
}

// 5. إنشاء الحاوية وتسجيل التبعيات
const container = new Container();
container.bind("INotificationService").to(EmailNotificationService);
container.bind(                    

توصيات