import Mediator from './Mediator'; import Colleague from './Colleague'; import 'reflect-metadata'; function mediatorFactory() { const mediator = new Mediator(); // 创建闭包 return { // 类装饰器 colleague: function(colleagueName: string) { return function(target: T) { // 劫持构造函数只为获得this return class extends target { static displayName = (target as any).displayName + '$Colleague'; constructor(...arg: any[]) { super(...arg); const colleague = new Colleague(colleagueName, this); // 从元数据中获取保存的公开的方法 Reflect.ownKeys(target.prototype).forEach(key => { if (typeof key === 'number') { key = key.toString(); } const actionMethod = Reflect.getMetadata('action', target.prototype, key); if (actionMethod) { colleague.setAction(actionMethod.name, actionMethod.value); } }); mediator.registColleague(colleague); } }; }; }, // 方法装饰器,开放的方法 colleagueAction: function(actionName: string) { return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) { // 将开放的方法放入中介,此时还未执行类装饰器,需要先保存起来 Reflect.defineMetadata('action', {name: actionName, value: descriptor.value}, target, propertyKey); }; }, // 方法装饰器 notifyMediator: function(colleagueName: string, actionName: string, ...payload: any[]) { return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) { // 劫持方法,通知中介 return { writable: true, enumerable: true, configurable: true, value: function(...args: any[]) { // tslint:disable-next-line:no-invalid-this let result = descriptor.value.apply(this, args); if (result instanceof Promise) { result.then(function() { mediator.notify(colleagueName, actionName, payload); }); } else { mediator.notify(colleagueName, actionName, payload); } return result; } }; }; } }; } export const {colleague, colleagueAction, notifyMediator} = mediatorFactory();