执行装饰器而不调用方法

问题描述 投票:0回答:1

我正在尝试将方法和函数注册到express中。例如:

@Controller("/api/users/")
export class UserController {

    constructor() {
        console.log("constructor")
    }

    @GET("get/:id")
    public getUser(req: Request, res: Response) {

    }
}

装饰器如下:

export function Controller(basePath: string) {
    return function(target: any) {
        const instance = new target();
        const methodList = Object.getOwnPropertyNames(target.prototype).map(m => target.prototype[m])
        methodList.forEach(method => {
            console.log(method) //<--- What should I put here?
        })
    }
}

export function GET(url: string) {
    return function (target: any, propertyKey: String, descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value;

        descriptor.value = function (...args: any[]) {
            descriptor.value.url = url
        }
        return descriptor;
    }
}

如何在不调用 getUser 函数的情况下获取值“get/:id”?

目标是将

getUser
引用到 Express 路由器。所以在这种情况下,我想将
getUser(req, res)
注册为
express.router.get(basePath + url, method)

我不知道该放什么来替换

console.log(method)
来注册方法

typescript express decorator
1个回答
0
投票

这个想法是让你的

GET
装饰器使用 reflect-metadata

存储 url

@Controller
被评估时,
@Get()
将会被执行并存储元数据。然后您所要做的就是检索所有存储的元数据。

export function Controller(basePath: string) {
    return function(target: any) {
        const instance = new target();
        const methodList = Object.getOwnPropertyNames(target.prototype).map(m => target.prototype[m])
        methodList.forEach(method => {
            const url = Reflect.getOwnMetadata("my-get-url", target.prototype, m)
        })
    }
}

export function GET(url: string) {
    return function (target: any, propertyKey: String, descriptor: PropertyDescriptor) {
    Reflect.defineMetadata("my-get-url", url, target, descriptor.propertyKey
    // ...
    }
}

请注意,如果您想让它与继承一起使用,这个简单的实现需要额外的工作。

这是我创建@aspectjs/core的原因之一。

使用aspectjs,你可以像这样简单地解决这个问题:

import {
  AnnotationFactory,
  AnnotationKind,
} from '@aspectjs/common';
import { Aspect, Compile, on, AdviceContext, getWeaver } from '@aspectjs/core';

// Define your annotations
const af = new AnnotationFactory('my-org');
const GET = af.create(AnnotationKind.METHOD, 'GET', (url: string) => {});
const Controller = af.create(AnnotationKind.CLASS, 'Controller', (url: string) => {});

// Create an aspect that registers your controller
@Aspect()
class RegisterExpressControllerAspect {
  @Compile(on.classes.withAnnotations(Controller))
  registerController(ctxt: AdviceContext) {
    
    const get = ctxt.annotations(GET).find({searchParents: true})[0]!;
    const [url] = get.args
    console.log(url)
  }
}

getWeaver().enable(new RegisterExpressControllerAspect())


@Controller("/api/users/")
export class UserController {

    constructor() {
        console.log("constructor")
    }

    @GET("get/:id")
    public getUser(req: Request, res: Response) {

    }
}
© www.soinside.com 2019 - 2024. All rights reserved.