การฉีดพึ่งพา - Angular2 DI - การเริ่มต้นอินสแตนซ์หลายตัวที่แตกต่างกันในตัวสร้างเดียวกัน
ฉันมีคำถามเกี่ยวกับ Angular2 DI สมมติว่าฉันมี TestService และฉันต้องการใช้ instance ของ service นี้ 2 ตัวที่แตกต่างกันภายใน component เดียวกัน ถ้าฉันเพียงแค่เพิ่ม provider ให้กับ component และเพิ่ม 2 instance เข้าไปใน constructor ฉันจะได้ instance ของ service เดียวกัน ตัวอย่างเช่น:
บริการทดสอบ
import {Injectable} from "@angular/core";
@Injectable()
export class TestService {
public id: number = Math.random();
public toString(): string {
return "Id: " + this.id;
}
}
ส่วนประกอบทดสอบ
import {Component, Input, OnInit} from "@angular/core";
import {TestService} from "../../services/test.service";
@Component({
providers: [TestService]
})
export class TestComponent implements OnInit {
constructor(private _testService1: TestService, private _testService2: TestService) { };
ngOnInit() {
console.log("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", this._testService1.toString());
console.log("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", this._testService2.toString());
}
}
ผลลัพธ์ในคอนโซล
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Id: 0.24242492129168425
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB Id: 0.24242492129168425
มีใครช่วยบอกได้ไหมว่ามีวิธีใช้กลไก DI ของ Angular2 เพื่อฉีดอินสแตนซ์ที่แตกต่างกันหลาย ๆ ตัวของบริการเดียวกันภายในคอมโพเนนต์เดียวกันได้หรือไม่ หรือว่าผมควรละเว้น DI สำหรับกรณีนี้และสร้างอินสแตนซ์ด้วยตัวเองผ่านคอนสตรักเตอร์?
ขอบคุณล่วงหน้า
คำตอบ #1
เนื่องจากมีจำนวนตัวอย่างจำกัด วิธีที่ตรงไปตรงมาอาจเป็น:
@Component({
providers: [
{ provide: 'TestService1', useClass: TestService },
{ provide: 'TestService2', useClass: TestService }
]
})
export class TestComponent implements OnInit {
constructor(
@Inject('TestService1') private _testService1: TestService,
@Inject('TestService2') private _testService2: TestService
) {}
...
}
หรือคู่มือ OpaqueToken เพื่อหลีกเลี่ยงการเขียนทับบริการที่มีตัวระบุสตริงเดียวกัน:
export const TestService1 = new OpaqueToken;
export const TestService2 = new OpaqueToken;
...
providers: [
{ provide: TestService1, useClass: TestService },
{ provide: TestService2, useClass: TestService }
]
...
constructor(
@Inject(TestService1) private _testService1: TestService,
@Inject(TestService2) private _testService2: TestService
) {}
มันไม่ทำร้าย DI ในตัวสร้างของ TestService และยังคงความสามารถในการทดสอบของ TestComponent ให้เท่าเทียมกัน ทั้งสองอินสแตนซ์ของบริการสามารถจำลองได้อย่างอิสระ
คำตอบ #2
คุณสามารถฉีดโรงงานที่ส่งกลับตัวอย่างใหม่ทุกครั้งที่คุณเรียกใช้งานได้:
@NgModule({
providers: [{
provide: 'testService',
useFactory: (/* TestService deps here like `http`*/) =>
(/* params */) => new TestService(/* http */),
deps: [/* TestService deps here like `Http`*/ ]
}]
})
@Component(...)
export class TestComponent implements OnInit {
constructor(@Inject('testService') private _testServiceFactory) { };
ngOnInit() {
console.log("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", this._testServiceFactory( /* params */).toString());
console.log("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", this._testServiceFactory().toString());
}
}
ตัวอย่าง Plunker (ตรวจสอบผลลัพธ์ในคอนโซลของเบราว์เซอร์เมื่อคุณคลิกปุ่ม)
