微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将变量传递给注入的服务以用作装饰器参数

如何解决将变量传递给注入的服务以用作装饰器参数

我有一个 Angular 项目,它使用的服务经常以典型的创建/读取/更新/删除/读取所有条目列表重复。我也经常想在接收到数据后以类似的方式操作接收到的数据。所以我编写了使用 sink(receiveValue:) 的装饰器,它以传递给它们的参数确定的方式“转换”数据(参数始终是一个对象类)。

在正常使用中,这看起来像这样:

UserProfileviewmodel

这种情况经常发生,所以我想编写一个可以扩展的父服务:

apply

问题是我不能对装饰器参数使用“this”,它在解析 IIRC 时不存在。但是有没有办法以某种方式将装饰器参数传递给我注入的服务,以便装饰器可以使用它?

还可以在下面找到“TransformObservable”装饰器:

//rule.service.ts
@Injectable({
  providedIn: 'root'
})
export class RuleService {

  rulesUrl: string = `${Constants.wikiApiUrl}/rule/`;

  constructor(private http: HttpClient) {}

  @TransformObservable(RuleObject)
  getRule(pk: number): Observable<Rule>{
    return this.http.get<Rule>(`${this.rulesUrl}/${pk}`);
  }
}

解决方法

this 关键字在函数作用域之外不可用。但是,您可以将所需的对象定义为同一类中的字段/属性,并且在装饰器注释中,您可以只传递装饰器函数将查找的字符串,或者传递实际的对象引用。

在装饰器中,检查传递给注解的参数:

if(typeof modelClass === 'string'){
  // lookup a property in decorated class definition
  modelClass = target[modelClass]; // or,this[modelClass]
}else {
  // assume modelClass is the needed object
}

这将允许您使用:

@TransformObservable('propertyName');
// or
@TransformObservable(someObjectReference);

targetthis 之间的区别:

传递给装饰器函数的target定义使用装饰器的类的对象。它将具有在类中定义的所有属性和方法,并可用于检索它们,如上所示。但是,target 不是您通常在类方法中使用的运行时 this。它唯一的替换方法 (descriptor.value) 将包含 this,就像原始方法一样。

因此,如果您真的需要 this 而不仅仅是修饰类定义,您必须将所有代码内部移动到替换函数 descriptor.value 中。在那里您可以访问 this 以及传递给装饰器和装饰器工厂的所有参数。

,

基于@S.D. 's answer 我终于明白他一直想说的话:您可以访问您放入descriptor.value 的匿名函数内的this。因此,为了让我的装饰器能够正确执行此操作,我必须使用 modelClass 从匿名函数内部访问 this,我很高兴。这是 S.D. 的解决方案看起来像付诸实践:

export function TransformObservable(modelClass: any){
    /**Decorator to apply transformObservableContent */
    return function(target: any,propertyKey: string,descriptor: PropertyDescriptor){

        const originalMethod = descriptor.value;
        descriptor.value = function(){
            const observable = originalMethod.apply(this,arguments);

            //If the decorator argument was not a class but instead a property
            // name of a property on the object that uses the decorator that 
            // contains the class,update the modelClass variable
            const decoratorArgumentIsProperty = ["String","string"].includes(typeof modelClass);
            if(decoratorArgumentIsTargetProperty){
                modelClass = this[modelClass];
            }

            return transformObservableContent(observable,modelClass);
        }
        return descriptor;
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。