decorate
概述
decorate 函数是一个实用程序,允许你以编程方式将装饰器应用于类、方法、属性和构造函数参数,而无需使用装饰器语法 (@decorator)。这在以下情况下特别有用:
- 你无法修改原始类以添加装饰器
- 你正在使用第三方类
- 你想有条件地应用装饰器
- 你处于装饰器语法不可用的环境中
API 参考
decorate 函数有多个重载来处理不同的装饰器类型:
function decorate(
decorators: ClassDecorator | ClassDecorator[],
target: Function
): void;
function decorate(
decorators: ParameterDecorator | ParameterDecorator[],
target: Function,
parameterIndex: number
): void;
function decorate(
decorators: MethodDecorator | PropertyDecorator | MethodDecorator[] | PropertyDecorator[],
target: Function,
property: string | symbol
): void;
export function decorate(
decorators: ParameterDecorator | ParameterDecorator[],
target: Function,
methodName: string | symbol,
parameterIndex: number,
): void;
示例
应用 ClassDecorator
使用此方法应用类级装饰器,如 @injectable():
class Katana implements Weapon {
public readonly damage: number = 10;
}
// Apply @injectable decorator using decorate function
decorate(injectable(), Katana);
const container: Container = new Container();
container.bind<Weapon>('Weapon').to(Katana);
const katana: Weapon = container.get<Weapon>('Weapon');
应用 ParameterDecorator
使用此方法将装饰器应用于构造函数参数,如 @inject():
@injectable()
class Warrior {
private readonly weapon: Weapon;
constructor(weapon: Weapon) {
this.weapon = weapon;
}
public fight(): string {
return `Fighting with weapon damage: ${this.weapon.damage.toString()}`;
}
}
// Apply @inject decorator to constructor parameter using decorate function
decorate(inject('Weapon'), Warrior, 0);
const container: Container = new Container();
container.bind<Weapon>('Weapon').to(Katana);
container.bind<Warrior>('Warrior').to(Warrior);
const warrior: Warrior = container.get<Warrior>('Warrior');
应用 PropertyDecorator
使用此方法将装饰器应用于类属性,如 @inject():
@injectable()
class Warrior {
public weapon!: Weapon;
public fight(): string {
return `Fighting with weapon damage: ${this.weapon.damage.toString()}`;
}
}
// Apply @inject decorator to property using decorate function
decorate(inject('Weapon'), Warrior, 'weapon');
const container: Container = new Container();
container.bind<Weapon>('Weapon').to(Katana);
container.bind<Warrior>('Warrior').to(Warrior);
const warrior: Warrior = container.get<Warrior>('Warrior');
应用 MethodDecorator
使用此方法将装饰器应用于类方法:
@injectable()
class Katana implements Weapon {
private _damage: number = 10;
public get damage(): number {
return this._damage;
}
public improve(): void {
this._damage += 2;
}
}
// Apply @postConstruct decorator to method using decorate function
decorate(postConstruct(), Katana, 'improve');
const container: Container = new Container();
container.bind<Weapon>('Weapon').to(Katana);
const katana: Katana = container.get<Weapon>('Weapon') as Katana;
用例
使用第三方类
当你需要使第三方类可注入但无法修改其源代码时:
import { decorate, injectable } from 'inversify';
import { SomeThirdPartyClass } from 'some-library';
// Make the third-party class injectable
decorate(injectable(), SomeThirdPartyClass);
条件装饰
根据运行时条件应用装饰器:
import { decorate, injectable } from 'inversify';
class MyService {
// Implementation
}
// Conditionally make it injectable
if (process.env.NODE_ENV === 'production') {
decorate(injectable(), MyService);
}
重要说明
- 必须在容器绑定中使用类之前调用
decorate函数 - 对于 ParameterDecorator,参数索引是从 0 开始的(第一个参数 = 0,第二个 = 1,依此类推)
- 你可以传递单个装饰器或装饰器数组