> 重要提示: **不要忘記用`@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
```