UNPKG

@malagu/core

Version:
75 lines (61 loc) 2.59 kB
import { inject, multiInject } from 'inversify'; import { ContainerUtil } from '../container'; import { ComponentId } from './component'; import { AnnotationUtil } from '../utils'; export interface AutowiredOption { id?: ComponentId, multi?: boolean; detached?: boolean } export type IdOrAutowiredOption = ComponentId | AutowiredOption; export const Autowired = function (idOrOption?: IdOrAutowiredOption): PropertyDecorator & ParameterDecorator { return (target: any, targetKey: string, index?: number) => { const option = parseAutowiredOption(target, targetKey, index, idOrOption); applyAutowiredDecorator(option, target, targetKey, index); }; }; export interface DoGetValue { (option: AutowiredOption, target: any, property: string): any; } export interface DoInject { (option: AutowiredOption, t: any, k: string, i?: number): any; } const defaultAutowiredOption: AutowiredOption = { multi: false, detached: false }; export function parseAutowiredOption(target: any, targetKey: string, index?: number, idOrOption?: IdOrAutowiredOption, ) { const option = AnnotationUtil.getValueOrOption<AutowiredOption>(idOrOption); const type = AnnotationUtil.getType(target, targetKey, index); if (type === Array) { option.multi = true; } option.id = option.id || type; return { ...defaultAutowiredOption, ...option }; } export function applyAutowiredDecorator(option: AutowiredOption, target: any, targetKey: string, index?: number, doInject: DoInject = ({ id, multi }, t: any, k, i) => multi ? multiInject(id!)(t, k, i) : inject(id!)(t, k, i), doGetValue: DoGetValue = ({ id, multi }, t, property) => multi ? ContainerUtil.getAll(id!) : ContainerUtil.get(id!)) { if (option.detached) { if (index !== undefined) { throw new Error(`The ${target.constructor.name} itself is not injected into the container, so the parameter injection of the constructor is not supported.`); } createAutowiredProperty(option, doGetValue, target, targetKey); } else { doInject(option, target, targetKey, index); } return option; } export function createAutowiredProperty(option: AutowiredOption, doGetValue: DoGetValue, target: any, property: string): void { let value: any; Object.defineProperty(target, property, { enumerable: true, get(): any { if (value !== undefined) { return value; } value = doGetValue(option, target, property); return value; } }); }