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

时间:2016-06-19 11:18:13

标签: dependency-injection typescript angular decorator

有没有办法使用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装饰器?

4 个答案:

答案 0 :(得分:9)

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

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方法在运行时函数执行期间获取依赖关系。 仍在寻找更好的解决方案。

答案 1 :(得分:4)

执行此操作有点棘手,因为装饰器在构建时执行,而不是在运行时执行。当执行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相关以来是否有任何重大变化到注射器 ApplicationRef ...

答案 2 :(得分:1)

在Angular 7中实现此目标的一种方法是:

app.module.ts

Array
(
    [0] => Array
        (
            [no_invoice] => INV0001
            [product_code] => 1111111
        )

    [1] => Array
        (
            [no_invoice] => INV0001
            [product_code] => 1111112
            [free_valie] => 839
            [count] => 1240
        )

)

decorator.service.ts

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

other.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;
  }
}

答案 3 :(得分:-4)

您可以执行以下操作:

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();