| وجه المقارنة المعمارية | حقن المُنشئ التقليدي (Constructor Injection) | دالة الحقن الحديثة (inject() Function) |
|---|---|---|
| موقع الحقن والتعريف | محصور حصرياً داخل دالة المُنشئ (`constructor`) للكلاس | متاح في نطاق تعريف الحقول، المتغيرات، أو كبارامترات افتراضية للدوال |
| التعامل مع الوراثة البرمجية (`Inheritance`) | يتطلب استدعاء `super()` مع تمرير كافة التبعيات صراحة للأب | أسهل بكثير ولا يفرض تمرير التبعيات عبر سلاسل الوراثة الطويلة |
| دعم البرمجة الوظيفية والـ Functions | غير ممكن، لأن المُنشئ مرتبط حصرياً بالكلاسات | ممكن تماماً، حيث يمكن استدعاء `inject()` داخل الدوال المستقلة (Functional Guards/Providers) |
في هندسة Angular 22.1 الحديثة، شكل الانتقال من الاعتماد الكلي على حقن المُنشئ (Constructor Injection) إلى دالة الحقن الفورية inject() نقلة نوعية كبرى. هذه الدالة المعمارية تتيح للمطور استدعاء الخدمات والتبعيّات في نطاق الحقول التصريحية (Field Initializers) أو حتى خارج صنف المكون تماماً، مما يمنح مرونة عالية جداً في إعادة استخدام الكود، وتسهيل الوراثة، والتخلص من تكرار متغيرات المُنشئ الطويلة.
تعمل دالة inject() حصرياً داخل "سياق الحقن المعتمد"، والذي يتوفر أثناء إنشاء الكلاس (في حقول الصنف أو المُنشئ) أو داخل المزودين الوظيفيين (Functional Providers & Guards). هذا يضمن أن أنگولر قادرة على تتبع العلاقات وتوفير التبعية الصحيحة.
تدعم دالة inject() خيارات متقدمة مثل optional() لجعل الخدمة اختيارية، أو skipSelf() لتجاوز المزود المحلي والبحث في النطاق الأب، مما يمنح المطور تحكماً دقيقاً يشبه الأنظمة الهندسية المعقدة.
| 1 | import { Injectable, signal } from '@angular/core'; |
| 2 | |
| 3 | @Injectable({ |
| 4 | providedIn: 'root' |
| 5 | }) |
| 6 | export class AnalyticsTrackerService { |
| 7 | private logsSignal = signal<string[]>([]); |
| 8 | |
| 9 | readonly logs = this.logsSignal.asReadonly(); |
| 10 | |
| 11 | trackAction(actionName: string) { |
| 12 | const timestamp = new Date().toLocaleTimeString(); |
| 13 | this.logsSignal.update(list => [`[${timestamp}] تم تنفيذ: ${actionName}`, ...list]); |
| 14 | } |
| 15 | } |
| 1 | <!-- inject-demo.component.html --> |
| 2 | <div class="inject-container"> |
| 3 | <h3>استعراض حقن التبعيات باستخدام دالة inject()</h3> |
| 4 | <p>هذا المكون يستخدم دالة الحقن الحديثة بدون الحاجة لكتابة constructor تقليدي.</p> |
| 5 | |
| 6 | <div class="action-panel"> |
| 7 | <button (click)="triggerAction()" class="track-btn">تسجيل حدث هندسي جديد</button> |
| 8 | </div> |
| 9 | |
| 10 | <div class="logs-box"> |
| 11 | <h4>سجل الأحداث المرصودة:</h4> |
| 12 | @for (log of analytics.logs(); track $index) { |
| 13 | <p class="log-item">{{ log }}</p> |
| 14 | } @empty { |
| 15 | <p class="empty-log">لا توجد أحداث مسجلة حتى اللحظة.</p> |
| 16 | } |
| 17 | </div> |
| 18 | </div> |
| 1 | /* inject-demo.component.css */ |
| 2 | .inject-container { |
| 3 | background: #090d16; |
| 4 | color: #fff; |
| 5 | padding: 24px; |
| 6 | border-radius: 12px; |
| 7 | border: 1px solid #1e293b; |
| 8 | } |
| 9 | |
| 10 | .action-panel { |
| 11 | margin: 16px 0; |
| 12 | } |
| 13 | |
| 14 | .track-btn { |
| 15 | background: #38bdf8; |
| 16 | color: #090d16; |
| 17 | border: none; |
| 18 | padding: 10px 20px; |
| 19 | border-radius: 6px; |
| 20 | font-weight: bold; |
| 21 | cursor: pointer; |
| 22 | } |
| 23 | |
| 24 | .track-btn:hover { |
| 25 | background: #7dd3fc; |
| 26 | } |
| 27 | |
| 28 | .logs-box { |
| 29 | background: #1e293b; |
| 30 | padding: 16px; |
| 31 | border-radius: 8px; |
| 32 | border: 1px solid #334155; |
| 33 | } |
| 34 | |
| 35 | .log-item { |
| 36 | font-family: monospace; |
| 37 | color: #34d399; |
| 38 | margin: 6px 0; |
| 39 | border-bottom: 1px dashed #334155; |
| 40 | padding-bottom: 4px; |
| 41 | } |
| 42 | |
| 43 | .empty-log { |
| 44 | color: #94a3b8; |
| 45 | font-style: italic; |
| 46 | } |
| 1 | import { Component, inject } from '@angular/core'; |
| 2 | import { CommonModule } from '@angular/common'; |
| 3 | import { AnalyticsTrackerService } from './analytics-tracker.service'; |
| 4 | |
| 5 | @Component({ |
| 6 | selector: 'app-inject-demo', |
| 7 | standalone: true, |
| 8 | imports: [CommonModule], |
| 9 | templateUrl: './inject-demo.component.html', |
| 10 | styleUrls: ['./inject-demo.component.css'] |
| 11 | }) |
| 12 | export class InjectDemoComponent { |
| 13 | // استخدام دالة inject مباشرة في حقل الصنف بدون constructor |
| 14 | readonly analytics = inject(AnalyticsTrackerService); |
| 15 | |
| 16 | triggerAction() { |
| 17 | this.analytics.trackAction('ضغط الزر الرئيسي وتحديث الواجهة'); |
| 18 | } |
| 19 | } |