有没有办法使用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
装饰器?
答案 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();