动态函数注入
在某些场景下,我们需要函数作为某个逻辑动态执行,而 IoC 中的对象属性则都是已经创建好的,无法满足动态的逻辑需求。
比如你需要一个工厂函数,根据不同的场景返回不同的实例,也可能有一个三方包,是个函数,在业务中想要直接调用,种种的场景下,你就需要直接注入一个函数,并且在函数中拿到上下文。
标准的函数注入样例。
export function contextHandler(context) {
return async () => {
// const xxx = context.getAsync('xxxx');
return true;
};
}
providerWrapper([
{
id: 'contextHandler',
provider: contextHandler,
}
]);
使用端。
@provide()
export class BaseService {
@inject()
contextHandler: () => boolean;
}
midway 通过 providerWrapper
函数来包裹一个函数,并且指定提供的 key,供其他 IoC 对象使用。由于函数直接传递了一个 context 对象,可以轻松的通过此对象拿到所需的其他对象,而不需要管理依赖。
函数注入大多数为了创建一个简单的工厂。
export function adapterFactory(context: IApplicationContext) {
return async (adapterName: string) => {
if (adapterName === 'google') {
return await context.getAsync('googleAdapter');
}
if (adapterName === 'baidu') {
return await context.getAsync('baiduAdapter');
}
// return await context.getAsync(adapterName + 'Adapter');
};
}
providerWrapper([
{
id: 'adapterFactory',
provider: adapterFactory,
}
]);
这样在业务中,可以直接来使用了。
@provide()
export class BaseService {
@config('adapterName')
adapterName;
@inject('adapterFactory')
factory;
adapter: Adapter;
@init()
async init() {
this.adapter = await this.factory(this.adapterName);
}
}
TIP
这个函数可以是异步的 (async)。
再举个例子,比如如果应用希望自己使用 sequelize, 而 sequelize 的创建 model 的过程是个异步操作,代码就可以这么写:
import { providerWrapper, IApplicationContext } from 'midway';
import * as Sequelize from 'sequelize';
import { Sequelize as SequelizeInstance } from 'sequelize';
// 可以直接写 async 方法
export async function factory(context: IApplicationContext) {
const instance = await context.getAsync<SequelizeInstance>('coreDB');
const UiKeyTraceModel = instance.define(name, {
gmtCreate: {
type: Sequelize.DATE,
allowNull: true,
field: 'gmt_create',
},
gmtModified: {
type: Sequelize.DATE,
allowNull: true,
field: 'gmt_modified',
}
}, {
timestamps: true,
createdAt: 'gmt_create',
updatedAt: 'gmt_modified',
freezeTableName: true,
tableName: 'xxxx'
});
return UiKeyTraceModel;
}
providerWrapper([
{
id: 'keyTraceModel',
provider: factory
}
]);
通过 providerWrapper
我们将一个原本的函数写法进行了包裹,和现有的依赖注入体系可以融合到一起,让容器能够统一管理。