InversifyJS: حاوية IoC لتطبيقات TypeScript

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

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

ابدأ الدورة

InversifyJS: حاوية IoC قوية لـ TypeScript

\n\n

InversifyJS هي حاوية IoC (عكس التحكم) خفيفة الوزن ولكنها قوية للغاية لتطبيقات TypeScript و JavaScript. وهي تنفذ نمط حقن التبعية (DI)، مما يسمح للمطورين بإنشاء أنظمة ضعيفة الاقتران وقابلة للاختبار وقابلة للتوسع. تستخدم المكتبة بشكل فعال إمكانيات TypeScript (الديكورات والأنواع) لضمان كتابة صارمة وسهولة في التطوير.

\n\n

تعتبر InversifyJS مثالية لتطبيقات الخادم على Node.js، وكذلك للمشاريع العميلة مع أطر عمل مثل Angular أو React أو Vue. في هذا الاستعراض، سنقوم بتحليل المفاهيم الأساسية ونوضح كيفية البدء بسرعة.

\n\n

المفاهيم الأساسية لـ InversifyJS

\n\n

قبل كتابة الكود، من المهم فهم الكيانات الرئيسية الثلاثة للمكتبة:

\n\n
    \n
  • الحاوية (Container) — الكائن المركزي الذي يدير جميع التبعيات. تقوم بتسجيل التجريدات وتطبيقاتها فيه.
  • \n
  • معرفات الخدمة (Service Identifiers) — مفاتيح فريدة تستخدمها الحاوية للعثور على التطبيق المطلوب. يمكن أن تكون سلاسل نصية أو رموزًا أو فئات.
  • \n
  • الديكورات — @injectable() و @inject() — تشير إلى TypeScript أن الفئة يمكن حقنها، وما هي التبعيات التي تحتاجها.
  • \n
\n\n

التثبيت والإعداد

\n\n

للبدء، قم بتثبيت InversifyJS وتبعياتها المطبعية:

\n\n
npm install inversify reflect-metadata --save\nnpm install --save-dev @types/node
\n\n

ثم أضف خيارين إجباريين إلى tsconfig.json:

\n\n
{\n  "compilerOptions": {\n    "emitDecoratorMetadata": true,\n    "experimentalDecorators": true,\n    "types": ["reflect-metadata"]\n  }\n}
\n\n

بعد ذلك، قم باستيراد reflect-metadata في الملف الرئيسي للتطبيق (عادةً index.ts أو main.ts):

\n\n
import "reflect-metadata";
\n\n

المثال الأول: خدمة بسيطة

\n\n

لنقم بإنشاء واجهة وتطبيقها. لاحظ الديكور @injectable():

\n\n
// interfaces/IWarrior.ts\nexport interface IWarrior {\n    fight(): string;\n}\n\n// entities/Warrior.ts\nimport { injectable } from "inversify";\n\n@injectable()\nexport class Warrior implements IWarrior {\n    fight(): string {\n        return "Warrior attacks with sword!";\n    }\n}
\n\n

الآن، لنقم بتسجيل هذا الارتباط في الحاوية والحصول على مثيل:

\n\n
import { Container } from "inversify";\nimport { IWarrior } from "./interfaces/IWarrior";\nimport { Warrior } from "./entities/Warrior";\n\nconst container = new Container();\n\n// تسجيل التجريد مع تطبيقه\ncontainer.bind<IWarrior>("IWarrior").to(Warrior);\n\n// الحصول على مثيل\nconst warrior = container.get<IWarrior>("IWarrior");\nconsole.log(warrior.fight()); // "Warrior attacks with sword!"
\n\n

حقن التبعيات عبر المُنشئ

\n\n

تتجلى القوة الحقيقية لحقن التبعية عندما تعتمد فئة على أخرى. استخدم الديكور @inject():

\n\n
// interfaces/IWeapon.ts\nexport interface IWeapon {\n    use(): string;\n}\n\n// entities/Sword.ts\nimport { injectable } from "inversify";\n\n@injectable()\nexport class Sword implements IWeapon {\n    use(): string {\n        return "Swing sword!";\n    }\n}\n\n// entities/Knight.ts\nimport { injectable, inject } from "inversify";\nimport { IWarrior } from "../interfaces/IWarrior";\nimport { IWeapon } from "../interfaces/IWeapon";\n\n@injectable()\nexport class Knight implements IWarrior {\n    private _weapon: IWeapon;\n\n    constructor(@inject("IWeapon") weapon: IWeapon) {\n        this._weapon = weapon;\n    }\n\n    fight(): string {\n        return this._weapon.use() + " The knight fights!";\n    }\n}
\n\n

تسجيل

توصيات