ディペンデンシ・インジェクション

ディペンデンシ・インジェクション (Dependency Injection, DI) はデザインパターンの一つです。 Angular には DI を実現する枠組みがあります。

DI はあるオブジェクトに他のサービスを取り入れる方法です。 特に、疎結合な形で干渉を少なく抑えつつ取り込むことを目指します。

ここでいう「サービス」というのは、例えば Windows サービスとかデーモンなどのバックグラウンドプロセスを指すのではありません。 Angular では「サービス」というモノに決まった形式はなく、「特定の機能を持ったまとまり」程度に考えます。

Angular ではあるオブジェクトを作成する際、コンストラクタのパラメータから、どのサービスに依存しているか知ります。

次の例は「従業員のリストを返すメソッド getEmployees をもつサービス EmployeeService」です。

import {Injectable} from '@angular/core';

@Injectable()
export class EmployeeService {
  getEmployees(){
    return [
      {
        lastname: 'Yamada',
        firstname: 'Hanako',
        title: 'Sales Representative'
      },
      {
        lastname: 'Suzuki',
        firstname: 'Ichiro',
        title: 'Manager'
      },
      {
        lastname: 'Smith',
        firstname: 'Kevin',
        title: 'CEO'
      }
    ];
  }
}

DI で使うサービスには @Injectable を付けます。

また、サービスはプロバイダとして、通常ルートモジュール (src/app/app.module.ts) に登録します。

import { BrowserModule } from '@angular/platform-browser';
...
import { EmployeeService } from './employee.service';

@NgModule({
  declarations: [
    AppComponent,
    ...
  ],
  imports: [
  ...
  ],
  providers: [
    EmployeeService
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

コンポーネントのメタデータに providers を記述することも可能です。

ルートモジュールにプロバイダを登録する場合は、 同じプロバイダのインスタンスをアプリケーション全体で共有することが可能ですが、コンポーネントのプロバイダとして登録した場合は、 コンポーネントが作成される度に新しいプロバイダのインスタンスが作成されます。

上記のサービス EmployeeService を DI で利用するときは、次のようにします。

import {Component} from '@angular/core';
import {EmployeeService} from './employee.service';

@Component({
  selector: 'employee-list',
  template: `
    <ul>
      <li *ngFor='let emp of employees'>
        <employee [employee]="emp"></employee>
      </li>
    </ul>`
})
export class EmployeeListComponent {
  employees;

  constructor(employeeService: EmployeeService){
    this.employees = employeeService.getEmployees();
  }
}

constructor のパラメータに EmployeeService 型の変数が設定されています。これによって、Angular はこの EmployeeList コンポーネントが EmployeeService という (インジェクタブルな) サービスを利用することがわかります。