| مستوى نطاق الحقن (DI Scope) | مكان التوفير والإنشاء (`Provider Location`) | دورة الحياة وتأثيره المعماري على التطبيق |
|---|---|---|
| مستوى المنصة (`Platform Level`) | يتم توفيره على مستوى المنصة ككل (`providedIn: 'platform'`) | يُنشئ نسخة واحدة مشتركة عبر عدة تطبيقات أو تطبيقات فرعية تتشارك نفس بيئة التشغيل |
| مستوى الجذر (`Root Level`) | يتم توفيره في الجذر (`providedIn: 'root'`) | يُنشئ نسخة واحدة (`Singleton`) تُشارك على مستوى التطبيق بالكامل طوال فترة تشغيله |
| مستوى المكون (`Component Level`) | يتم تعريفه داخل مصفوفة `providers` الخاصة بالمكون نفسه | يُنشئ نسخة جديدة مستقلة مع كل عملية إنشاء للمكون، وتُدمر الخدمة تلقائياً عند تدمير المكون |
لا يتم التعامل مع نظام حقن الاعتماديات (DI) ككتلة واحدة مسطحة، بل يعتمد على شجرة هرمية متكاملة تتوافق هيكلياً مع شجرة المكونات في التطبيق. فهم مستويات ونطاقات الحقن (Scopes) يمنح المطور قدرة دقيقة على التحكم في دورة حياة الخدمات، وتحديد ما إذا كان يجب أن تكون الخدمة مشتركة على مستوى التطبيق بالكامل (Singleton) أو مخصصة لمكون معين وشجرته الفرعية.
عندما يطلب مكون خدمة معينة، يبدأ أنگولر بالبحث عنها في المزود المحلي للمكون (Component Providers)، فإن لم يجدها يصعد تدريجياً نحو الأب إلى أن يصل إلى الجذر (Root) والمنصة (Platform)، مما يتيح لك إعادة تعريف الخدمات في نطاقات فرعية عند الحاجة.
توفير الخدمات على مستوى المكون يسمح لكل نسخة من المكون بامتلاك حالة مستقلة تماماً لا تتأثر بنسخ المكونات الأخرى، وهو أمر مثالي للمكونات المعقدة التي تتطلب بيانات خاصة بها.
| 1 | import { Injectable } from '@angular/core'; |
| 2 | |
| 3 | // لاحظ عدم استخدام providedIn: 'root' لكي يتم التحكم بنطاقها محلياً |
| 4 | @Injectable() |
| 5 | export class ScopedCounterService { |
| 6 | private count = 0; |
| 7 | |
| 8 | getCount(): number { |
| 9 | return this.count; |
| 10 | } |
| 11 | |
| 12 | increment(): void { |
| 13 | this.count++; |
| 14 | } |
| 15 | } |
| 1 | import { Component, inject } from '@angular/core'; |
| 2 | import { CommonModule } from '@angular/common'; |
| 3 | import { ScopedCounterService } from './scoped-counter.service'; |
| 4 | |
| 5 | @Component({ |
| 6 | selector: 'app-scoped-counter', |
| 7 | standalone: true, |
| 8 | imports: [CommonModule], |
| 9 | // توفير الخدمة محلياً يعني أن كل نسخة من هذا المكون ستمتلك عداداً مستقلاً بذاته |
| 10 | providers: [ScopedCounterService], |
| 11 | template: ` |
| 12 | <div class="scoped-container"> |
| 13 | <h3>مستويات وحقن الاعتماديات النطاقية (Hierarchical DI)</h3> |
| 14 | <p class="counter-val">القيمة المحلية للعداد: <strong>{{ counterService.getCount() }}</strong></p> |
| 15 | <button (click)="increment()" class="action-btn">زيادة العداد المحلي</button> |
| 16 | </div> |
| 17 | `, |
| 18 | styles: [` |
| 19 | .scoped-container { background: #090d16; color: #fff; padding: 24px; border-radius: 12px; border: 1px solid #1e293b; margin-top: 10px; } |
| 20 | .counter-val { background: #1e293b; padding: 12px; border-radius: 6px; color: #38bdf8; font-weight: bold; } |
| 21 | .action-btn { background: #10b981; color: #090d16; border: none; padding: 8px 16px; border-radius: 6px; font-weight: bold; cursor: pointer; margin-top: 8px; } |
| 22 | `] |
| 23 | }) |
| 24 | export class ScopedCounterComponent { |
| 25 | readonly counterService = inject(ScopedCounterService); |
| 26 | |
| 27 | increment() { |
| 28 | this.counterService.increment(); |
| 29 | } |
| 30 | } |
⚠️ تحذير
الوقوع في فخ إنشاء نسخ متعددة بالخطأ! وضع خدمة يفترض أن تكون Singleton (مثل خدمة الاتصال بقاعدة البيانات أو حالة المستخدم العامة) داخل مصفوفة providers لمكون فرعي سيؤدي إلى إنشاء نسخة جديدة وعزلة كاملة قد تكسر منطق مزامنة البيانات في التطبيق.