ค้นหาเว็บไซต์

การฉีดพึ่งพา - 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 (ตรวจสอบผลลัพธ์ในคอนโซลของเบราว์เซอร์เมื่อคุณคลิกปุ่ม)

บทความที่เกี่ยวข้อง