0. 설치
npm install reflect-metadata
1. 파라미터 데코레이터 정의
import "reflect-metadata";
export const ParamSymbols = {
query : Symbol("ParamQuery"),
param : Symbol("ParamParam"),
}
function InjectSymbol(symbol: Symbol, target: any, key: string | symbol, index: number) {
const existingParameterDecorators = Reflect.getMetadata(symbol, target, key) || [];
Reflect.defineMetadata(symbol, [...existingParameterDecorators, index], target, key);
}
/** HTTP Request Query */
export function ReqQuery(target: any, key: string | symbol, index: number) {
InjectSymbol(ParamSymbols.query, target, key, index);
}
/** HTTP Request Params */
export function ReqParam(target: any, key: string | symbol, index: number) {
InjectSymbol(ParamSymbols.param, target, key, index);
}
2. 메소드 데코레이터 정의
import { ParamSymbols } from "../decorator/param-decorator";
export function ControllerBody(target: any, name: string, descriptor: PropertyDescriptor) {
// 원본 함수
const originFunc = descriptor.value;
// 파라미터 목록
const paramTypes: any[] = Reflect.getMetadata('design:paramtypes', target, name);
// 데코레이터 적용 인덱스 위치
const posQueryDeco : number[] = Reflect.getMetadata(ParamSymbols.query, target, name);
const posParamDeco : number[] = Reflect.getMetadata(ParamSymbols.param, target, name);
const wrappedFunc = async function (...args: any[]) {
// 각 파라미터마다 사용된 데코레이터에 알맞게 처리
paramTypes.forEach((paramType: any, index: number) => {
if(posQueryDeco?.includes(index)) {
args[index] = {}; // Request Query
}
else if(posParamDeco?.includes(index)) {
args[index] = {}; // Request Param
}
});
return await originFunc.apply(this, args);
};
descriptor.value = wrappedFunc;
}
3. 사용 예시
@ControllerBody
public static async Func(
@ReqQuery q: any,
@ReqParam p: any,
a1: any,
b2: any,
) {
// ...
return 1;
}