亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何使用類裝飾器將裝飾器應用于所有類方法

如何使用類裝飾器將裝飾器應用于所有類方法

繁星coding 2022-12-29 14:13:27
我正在使用實驗性打字稿裝飾器來管理 express 中的訪問控制。class AccountController extends Controller {    login(req: Request, res: Response) {    const { email, password } = req.body;    const token = await this.model.login(email, password);    return res.json({      token    });  }  @hasRole('ADMIN')  list(req: Request, res: Response) {    res.json({      data: await this.model.findAll()    });  }}hasRole方法裝飾器工作正常,我很滿意。Controller實現 REST 方法:class Controller {  list(req: Request, res: Response) { // impl }  get(req: Request, res: Response) { // impl }   create(req: Request, res: Response) { // impl }  update(req: Request, res: Response) { // impl }  delete(req: Request, res: Response) { // impl }}問題是,我必須對大多數其他控制器應用相同的裝飾器,而且我發現它非常重復。例如,StockController應該只允許訪問MERCHANT角色,我必須執行如下操作:class StockController extends Controller {  @hasRole('MERCHANT')  list(req: Request, res: Response) {     return super.list(req, res);  }  @hasRole('MERCHANT')  get(req: Request, res: Response) {     return super.get(req, res);  }   @hasRole('MERCHANT')  create(req: Request, res: Response) {     return super.create(req, res);  }  @hasRole('MERCHANT')  update(req: Request, res: Response) {     return super.update(req, res);  }  @hasRole('MERCHANT')  delete(req: Request, res: Response) {     return super.delete(req, res);  }}這種方法不僅乏味和重復而且不安全,因為如果我添加了一個方法Controller并且不小心忘記了將方法添加到子控制器,它們將允許不需要的訪問。我想用類裝飾器處理這個問題并使用如下內容:@requireRole('MERCHANT')class StockController extends Controller {}但是,根據我在文檔中看到的內容:類裝飾器應用于類的構造函數,可用于觀察、修改或替換類定義。據我了解,我無法在類裝飾器中實現“方法掛鉤”。有什么建議么?供您參考,hasRole裝飾器如下所示:export function hasRole(role: string) {  return function(target: Object, propertyKey: string, descriptor: PropertyDescriptor) {    const originalMethod = descriptor.value;    descriptor.value = function(req: Request, res: Response) {      const user = res.locals.user;      if (user && user.hasRole(role)) {        originalMethod.apply(this, [req, res]);      } else {        res.status(403).json({});      }    }  }}
查看完整描述

1 回答

?
蕭十郎

TA貢獻1815條經驗 獲得超13個贊

這可以通過覆蓋類方法來實現


function AttachToAllClassDecorator<T>(someParam: string) {

    return function(target: new (...params: any[]) => T) {

        for (const key of Object.getOwnPropertyNames(target.prototype)) {

            // maybe blacklist methods here

            let descriptor = Object.getOwnPropertyDescriptor(target.prototype, key);

            if (descriptor) {

                descriptor = someDecorator(someParam)(key, descriptor);

                Object.defineProperty(target.prototype, key, descriptor);

            }

        }

    }

}

基本上遍歷所有方法(可能圍繞它添加一些邏輯以將某些方法列入白名單/黑名單)并用包裝了方法裝飾器的新方法覆蓋。


這是方法裝飾器的基本示例。


function someDecorator(someParam: string): (methodName: string, descriptor: PropertyDescriptor) => PropertyDescriptor {

    return (methodName: string, descriptor: PropertyDescriptor): PropertyDescriptor => {

        let method = descriptor.value;


        descriptor.value = function(...args: any[]) {

            console.warn(`Here for descriptor ${methodName} with param ${someParam}`);


            return method.apply(this, args);

        }


        return descriptor;

    }

}

TS游樂場


查看完整回答
反對 回復 2022-12-29
  • 1 回答
  • 0 關注
  • 138 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號