繁体   English   中英

Angular 2 - 将依赖项注入装饰器工厂

[英]Angular 2 - Inject a dependency into a decorator factory

有没有办法使用Angular的DI将依赖项注入装饰器工厂? 我们将以下代码作为简化示例:

@Component({
  selector: 'hello-component',
  template: '<div>Hello World</div>'
})
export class HelloComponent {
  @PersonName()
  name: string;

  ngAfterViewInit() {
    console.log(`Hello, ${this.name}`);
  }
}

这里, PersonName装饰器的预期行为是它访问Person依赖项,并使用它来设置类的name属性。

是否有可能为上面的代码实现PersonName装饰器?

目前,要将依赖项注入我的装饰器(以及其他额外的模块类),我正在使用此解决方法:

import {Injectable, Injector} from "@angular/core";
@Injectable()
export class ExtraModuleInjector {
  private static injector;

  public static get(token: any) {
    if (ExtraModuleInjector.injector) {
      return ExtraModuleInjector.injector.get(token);
    }
  }

  constructor(public injector: Injector) {
    ExtraModuleInjector.injector = injector;
  }
}

在注入根组件后,它允许使用静态get方法在运行时函数执行期间获取依赖关系。 仍在寻找更好的解决方案。

这样做有点棘手,因为装饰器是在构建时执行的,而不是在运行时执行的。 当执行decorator时,没有该类的实例。

回到ng2.beta.10,我用它来从服务中获取数据(不要认为你可以从组件,但我可能是错的......):

// some-route.ts
@CanActivate((next, prev) => {
  let store: any = getSingleton(Store);
})

// injector.ts
import {Injector} from 'angular2/core'

let appInjectorRef: Injector;

export const appInjector = (injector?: Injector) => {
  if (injector)
    appInjectorRef = injector;
  return appInjectorRef;
}

export function getSingleton(token: any) {
  let injector: Injector = appInjector();
  return injector.get(token);
}

..老实说,现在看看这段代码,我不知道它是如何工作的(但我知道它当时就已经做过了。不确定现在的状态是什么,或者自从beta.10与Injector有关后是否有任何重大变化和ApplicationRef ......

在Angular 7中执行此操作的一种方法是:

app.module.ts

import { setInjector } from './service/inj.service';
@NgModule({..})
export class AppModule {
  constructor(i: Injector) {
    setInjector(i)
  }
}

decorator.service.ts

import { Injectable, Injector } from '@angular/core';

let injector: Injector;
export const setInjector = (i: Injector)=>{
  injector = i
}

export function mydecorator(arg:any){
  let service: SomeServiceWhichNeedsToBeInjected
  return (target, key, descriptor)=>{
    if(descriptor === undefined) {
      descriptor = Object.getOwnPropertyDescriptor(target, key)
    }
    var originalMethod = descriptor.value
    descriptor.value = function () {
      if(!loading){
        service= injector.get(SomeServiceWhichNeedsToBeInjected)
      }
      //do something with service
      return originalMethod.apply(this, arguments)
    }
    return descriptor;
  }
}

other.service.ts

@mydecorator('somearg')
decoratedmethod(arg1){
  //..
}

你可以这样做:

export class AnnotationExample {
  @PersonName
  name: string;

  constructor() {
    alert(this.name);
  }
}

function PersonName(/*target: Function, fnName: string, fn: any*/) {
  return {value: 'amit'};
}

var whatIs = new AnnotationExample();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM