属性注入

原文链接

InversifyJS 支持属性注入,因为有时候构造器注入并不是最好的注入模式。当然了,在大多数情况下,您仍旧应该避免使用属性注入而采用构造器注入的方式。

如果是类在没有依赖项无法工作的情况下,应当将其添加到构造函数中。这个类需要一些新的依赖,因此你希望你的更改会破坏一些东西。另外,创建一个未完全初始化(“两步构建”)的类其实是一种反模式(IMHO,in my humble opinion,依我拙见).如果类可以在没有依赖项的情况下工作,设置setter即可。

来源 stackoverflow

下面两种情况您可能会考虑使用属性注入:

  • 当我们能够使用InversifyJS来创建类的实例的时候。
  • 当我们无法使用InversifyJS来创建类的实例的时候。

我靠,你在逗我?其实,在不同的场景情况需要不同的属性注入实现方式。

当我们能够使用InversifyJS来创建类的实例的时候

如果您正在使用的库或框架允许InversifyJS在应用中创建类的实例,那么您可以使用@inject装饰器注入属性:

import { injectable, inject, container } from "inversify";

@injectable()
class PrintService {
    // ...
}

@injectable()
class Summary {
    // ...
}

@injectable()
class Author {
    // ...
}

@injectable()
class Book {

  private _author: Author;
  private _summary: Summary;

  @inject("PrintService")
  private _printService: PrintService;

  public constructor(
      @inject("Author") author: Author,
      @inject("Summary") summary: Summary
) {
    this._author = author;
    this._summary = summary;
  }

  public print() {
     this._printService.print(this);
  }

}

let container = new Container();
container.bind<PrintService>("PrintService").to(PrintService);
container.bind<Author>("Author").to(Author);
container.bind<Summary>("Summary").to(Summary);
container.bind<Book>("Book").to(Book);

// Book instance is created by InversifyJS
let book = container.get<Book>("Book");
book.print();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

我们的单元测试这里有更多例子嗷。

当我们无法使用InversifyJS来创建类的实例的时候

InversifyJS的设计方式使其能够与尽可能多的库和框架进行集成。但是,它的许多功能需要在应用内部创建类的实例。

这就产生了一个问题,一些框架接管了创建实例的控制权。比方说,React会接管传入组件的实例创建权。

我们开发了一个工具来方便您在InversifyJS尚未创建实例的情况下注入属性:

import getDecorators from "inversify-inject-decorators";
import { Container, injectable  } from "inversify";

@injectable()
class PrintService {
    // ...
}

let container = new Container();
container.bind<PrintService>("PrintService").to(PrintService);
let { lazyInject } = getDecorators(container);

class Book {

  private _author: string;
  private _summary: string;

  @lazyInject("PrintService")
  private _printService: PrintService;

  public constructor(author: string, summary: string) {
    this._author = author;
    this._summary = summary;
  }

  public print() {
     this._printService.print(this);
  }

}

// Book 的实例并不是由 InversifyJS 创建的
let book = new Book("Title", "Summary");
book.print();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

这个工具模块就是inversify-inject-decorators,它内置了下面的装饰器:

  • @lazyInject用于在没有元数据的情况下注入属性。
  • @lazyInjectNamed用于在没有具名元数据的情况下注入属性。
  • @lazyInjectTagged用于在没有带标签元数据的情况下注入属性。
  • @lazyMultiInject用于多重注入。

请访问这里进一步了解。

上次更新: 1/14/2020, 4:49:04 PM