> 重要提示: **不要忘记用`@Service`装饰器声明你的类!**被注入的和请求依赖的那些都应该被声明。
*****
## 注册依赖关系
有三种方法来注册你的依赖关系。
* 用`@Service()`装饰器注解一个类([链接]())
* 用`Token`注册一个值
* 用一个字符串标识符来注册一个值
`Token`和字符串标识符可以用来注册类以外的其他值。`Token`和字符串标识符都可以注册任何类型的值,包括除`undefined`之外的原始值。它们必须在容器上用`Container.set()`函数设置,然后才能通过`Container.get()`请求它们。
```
import 'reflect-metadata';
import { Container, Inject, Service, Token } from 'typedi';
const myToken = new Token('SECRET_VALUE_KEY');
Container.set(myToken, 'my-secret-value');
Container.set('my-config-key', 'value-for-config-key');
Container.set('default-pagination', 30);
// 在你应用的其他地方
const tokenValue = Container.get(myToken);
const configValue = Container.get('my-config-key');
const defaultPagination = Container.get('default-pagination');
```
*****
## 注入依赖
有三种方法可以注入你的依赖关系。
* 通过类的构造函数参数自动注入
* 用`@Inject()`装饰器来注解类属性
* 直接使用`Container.get()`来请求一个类、`Token`或字符串标识符的实例。
### 构造函数参数注入
任何已经用`@Service()`装饰器标记的类,它的构造器属性将会被自动注入正确的依赖关系。
**TypeDI将用于解决依赖关系的容器实例插入到构造函数的最后一个参数中。**
```
import 'reflect-metadata';
import { Container, Inject, Service } from 'typedi';
@Service()
class InjectedClass {}
@Service()
class ExampleClass {
constructor(public injectedClass: InjectedClass) {}
}
const instance = Container.get(ExampleClass);
console.log(instance.injectedClass instanceof InjectedClass);
// 输出为true,因为TypeDI将InjectedClass的实例分配给了属性。
```
### 属性注入
当父类被TypeDI初始化时,任何被`@Inject`装饰器标记的属性将被自动分配给该类的实例。
```
import 'reflect-metadata';
import { Container, Inject, Service } from 'typedi';
@Service()
class InjectedClass {}
@Service()
class ExampleClass {
@Inject()
injectedClass: InjectedClass;
}
const instance = Container.get(ExampleClass);
console.log(instance.injectedClass instanceof InjectedClass);
// 输出为true,因为InjectedClass的实例已经被TypeDI分配到`injectedClass`属性中。
```
### 使用`Container.get()`
`Container.get()`函数可以直接用来请求一个目标类型的实例。TypeDI将解析并初始化所有对目标类的依赖。`Container.get()`可以被用来请求:
* 一个可构造的值(类定义),它将返回类的实例
* `Token`,它将返回为该Token注册的值
* 字符串,它将返回用该名称注册的值
```
import 'reflect-metadata';
import { Container, Inject, Service, Token } from 'typedi';
const myToken = new Token('SECRET_VALUE_KEY');
@Service()
class InjectedClass {}
@Service()
class ExampleClass {
@Inject()
injectedClass: InjectedClass;
}
/** Tokens必须在容器中明确设置所需的值 */
Container.set(myToken, 'my-secret-value');
/** 字符串标识符必须在容器中明确设置为所需的值. */
Container.set('my-dependency-name-A', InjectedClass);
Container.set('my-dependency-name-B', 'primitive-value');
const injectedClassInstance = Container.get(InjectedClass);
// 可以请求一个没有依赖关系的类
const exampleClassInstance = Container.get(ExampleClass);
// 可以请求一个有依赖关系的类,并且依赖关系将被解决。
const tokenValue = Container.get(myToken);
// tokenValue 将是 'my-secret-value'
const stringIdentifierValueA = Container.get('my-dependency-name-A');
// stringIdentifierValueA 将是 InjectedClass 的实例。
const stringIdentifierValueB = Container.get('my-dependency-name-B');
//stringIdentifierValueB 将是 'primitive-value'
```
*****
## 单例与暂存类
每个注册的 Service 默认都是一个单例。这意味着对`Container.get(MyClass)`的重复调用将返回同一个实例。如果这不是我们想要的行为,可以通过`@Service()`装饰器将一个类标记为瞬时的:
```
import 'reflect-metadata';
import { Container, Inject, Service } from 'typedi';
@Service({ transient: true })
class ExampleTransientClass {
constructor() {
console.log('I am being created!');
// 这将被输出两次
}
}
const instanceA = Container.get(ExampleTransientClass);
const instanceB = Container.get(ExampleTransientClass);
console.log(instanceA !== instanceB);
// prints true
```