gpt4 book ai didi

Angular2 DI : Inject a new value on every injection?

转载 作者:搜寻专家 更新时间:2023-10-30 21:19:43 25 4
gpt4 key购买 nike

我使用 Angular2 DI 在各种服务和组件中注入(inject)一个 Logger 类。是否可以在每次请求 Logger 时创建并注入(inject)一个新对象?我尝试了 FactoryProvider;它实例化一个实例一次,然后在所有地方注入(inject)相同的实例。

为每个组件注册一个单独的 Logger 提供程序可以解决这个问题,但这似乎有点矫枉过正。

到目前为止,我还没有找到更好的解决方案,但它会让我的事情变得更加方便。

示例

这是我 super 方便的目标:

// logger.service.ts
export class Logger {
static LoggerProvider: FactoryProvider = {
provide: Logger,
useFactory: () => {
return new Logger();
},
/* Actually we need a LoggerService here, I omitted that. */
};
name: string;
info(msg: string) { console.log('INFO', this.name, msg); }
}

// status.service.ts
@Injectable()
export class StatusService {
constructor(private log: Logger) {
this.log.name = 'StatusService';
this.log.info('ctor'); // logs "INFO StatusService ctor"
}
test() {
this.log.info('test'); // should log "INFO StatusService test"
}
}

// home.component.ts
@Component({ /* ... */})
export class HomeComponent {
constructor(
private statusService: StatusService
private log: Logger,
) {
// Got the same logger as the StatusService!!!
this.log.name = 'HomeComponent';
this.log.info('ctor'); // logs "INFO HomeComponent ctor"
this.statusService.test(); // breaks and logs "INFO HomeComponent test"!!!
}

}

这现在可以完成,但是,它需要更多样板文件:

// status.service.ts
@Injectable()
export class StatusService {
private log: Logger;
constructor(loggerService: LoggerService) {
this.log = loggerService.createLogger('StatusService');
this.log.info('ctor'); // logs "INFO StatusService ctor"
}
test() {
this.log.info('test'); // definitely logs "INFO StatusService test"
}
}

更多更新

好吧,我正在挖掘 Angular2 问题跟踪器并找到了 this guy (#18015)他们争论解决这个问题的 DI 扩展以及它将影响整个 DI 机制的方式。这似乎是真正的解决方案,但目前还没有定论。 (@bryan60 似乎是对的:目前——5.0.0-rc.1——这是不支持的。)

最佳答案

实际上可以在每次请求时创建一个 Logger。想想 ActivatedRoute,你会为不同路由下的不同组件获得不同的实例。

我们的想法是创建一个自定义注入(inject)器。

import { Component, OnInit } from '@angular/core';

@Component({
selector: 'app-container-outlet',
template: '<router-outlet></router-outlet>',
})
export class AppContainerOutletComponent { }


@Directive({
selector: 'some-root-container',
})
export class AppContainerDirective implements OnInit {
private content: ComponentRef<any> | null;
constructor(
private vcr: ViewContainerRef,
private cdr: ChangeDetectorRef,
private resolver: ComponentFactoryResolver,
private router: Router
) { }

ngOnInit() {
const factory = this.resolver.resolveComponentFactory(AppContainerOutletComponent);
const injector = new ContainerInjector(this.router, this.vcr.injector);
this.content = this.vcr.createComponent(factory, this.vcr.length, injector);
this.cdr.markForCheck();
}
}

class ContainerInjector implements Injector {
constructor(
private router: Router,
private parent: Injector
) {}

get(token: any, notFoundValue?: any): any {
if (token === Logger) {
return new Logger(/* You can also pass some parameters to Logger */);
}

return this.parent.get(token, notFoundValue);
}
}

然后只需使用 some-root-container 而不是 router-outlet(只需要替换根容器)。请注意,实际上 some-root-container 中不需要 router-outlet。您只需要创建一个带有自定义注入(inject)器的组件,并使其他所有组件成为该组件的子组件。

然后,像往常一样注入(inject) Logger(不要在任何地方提供)。每次都会得到一个新的 Logger 实例。

缺点是不会调用 Logger 上的 ngOnDestroy(如果已实现)。

希望对您有所帮助。

关于Angular2 DI : Inject a new value on every injection?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46573239/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com