依赖注入 – 如何在Angular2中正确使用依赖注入?

前端之家收集整理的这篇文章主要介绍了依赖注入 – 如何在Angular2中正确使用依赖注入?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我在解决DI问题方面取得了成功.我已经阅读了一些教程并获得了jist但是在使用我的自定义服务制作了一些嵌套的DI后,事情开始崩溃了.

有人可以解释何时使用useFactory而不是useClass?我已经看过ng2文档,我已经看过这些例子,但是我无法将它们映射到我的问题中.目前我的引导程序看起来像这样:

  1. bootstrap(
  2. App,[
  3. FORM_PROVIDERS,ROUTER_PROVIDERS,HTTP_PROVIDERS,provide(LocationStrategy,{ useClass: PathLocationStrategy }),provide(RequestOptions,{ useClass: DefaultRequestOptions }),provide(MsgService,{ useClass: MsgService }),provide(HttpAdvanced,{ useFactory: (MsgService,HTTP_PROVIDERS) => new HttpAdvanced(MsgService,HTTP_PROVIDERS),deps: [MsgService,HTTP_PROVIDERS] }),provide(AuthService,{ useFactory: (HttpAdvanced) => new AuthService(HttpAdvanced),deps: [HttpAdvanced,MsgService] }),provide(FormBuilderAdvanced,{ useFactory: (FormBuilder,HttpAdvanced) => new FormBuilderAdvanced(FormBuilder,HttpAdvanced),deps: [FormBuilder,HttpAdvanced] }),provide(MsgServiceInternal,{ useClass: MsgServiceInternal })
  4. ]
  5. );

我的最新一期是:

  1. EXCEPTION: Error during instantiation of AuthService! (HeaderBar -> AuthService).
  2. ORIGINAL EXCEPTION: TypeError: this.http.get is not a function

我的依赖项就像

  1. HttpAdvanced -> Http(ng2),MsgService
  2. MsgService -> MsgServiceInternal
  3. AuthService -> HttpAdvanced
  4. FormBuilderAdvanced -> FormBuilder(ng2),HttpAdvanced

1.我是否正确使用了provide / useClass / useFactory,我如何提供具有其他依赖关系的服务?

此外,我在我的代码中的一个地方:

  1. static isUserInjector() {
  2. return (next,prev) => Injector.resolveAndCreate([AuthService,{ useClass: HttpAdvanced })]).get(AuthService).isUser();
  3. }

因为我想拥有一个我提供的功能

  1. @CanActivate(AuthService.isEditorInjector())

但是我不能使用构造函数注入,因为@CanActivate在类范围之外,所以我不能在控制器中注入服务然后引用像@CanActivate(this.authService.isEditor())

2.对此有什么好的解决方案?

一些代码

  1. @Component({
  2. selector: 'ShowStats',templateUrl: './dest/views/showStats/showStats.html',directives: [ COMMON_DIRECTIVES,UsersCount,AdminsList,GlobalWishlist,PopularTrack ]
  3. })
  4. export class ShowStats {
  5. authService : AuthService;
  6.  
  7. constructor( authService : AuthService ){
  8. this.authService = authService;
  9. }
  10. }
  11.  
  12. ... next file ...
  13.  
  14. @Injectable()
  15. export class HttpAdvanced {
  16. msgService: MsgService;
  17. http: Http;
  18.  
  19. constructor(msgService: MsgService,http: Http) {
  20. this.msgService = msgService;
  21. this.http = http;
  22. }
  23.  
  24. /*
  25. * This is for plain ol' GET requests .. with callback of course.
  26. */
  27. public get(url,callback) {
  28. return this.http.get(url).subscribe((res) => {
  29. let data = res.json().data;
  30. callback(data);
  31. },this.msgService.httpErrorHandler);
  32. }
  33. .... other code for HttpAdvanced

3.
导入文件的顺序对DI是否重要?我想我注意到,因为我在同一个文件中有MsgService和MsgServiceInternal,并且MsgService依赖于Internal,我之前必须放置Internal但是我不是100%它是否与导入顺序相同?

4.
所以,如果我只是这样做:

  1. bootstrap(
  2. App,MsgService,HttpAdvanced,AuthService,FormBuilderAdvanced,MsgServiceInternal
  3. ]
  4. );

我明白了:

  1. Cannot resolve all parameters for 'FormBuilderAdvanced'(?,?).
  2. Make sure that all the parameters are decorated with Inject or have
  3. valid type annotations and that 'FormBuilderAdvanced' is decorated
  4. with Injectable.

我曾经用useFactory删除这个错误,但我现在很困惑.这是否意味着没有注入deps,因为它看不到它们或什么?

Form类:

  1. export class FormBuilderAdvanced {
  2. http: HttpAdvanced;
  3. fb: FormBuilder;
  4.  
  5. constructor(fb: FormBuilder,http: HttpAdvanced) {
  6. this.fb = fb;
  7. this.http = http;
  8. }
  9.  
  10. create(controlNames: string[],submissionUrl: string,getter?: any) {
  11. return new Form(this.fb,this.http,controlNames,submissionUrl,getter);
  12. }
  13. }
你的问题没有提供足够的信息来确定,但这可能已经足够了
  1. bootstrap(
  2. App,// provide(MsgService,// is just fine when no special behavior is required
  3. // provide(HttpAdvanced,provide(Http,{useClass: HttpAdvanced});
  4. AuthService,provide(FormBuilder,{ useClass: FormBuilderAdvanced}),MsgServiceInternal)
  5. ]
  6. );

如果要使类可用于注入,只需将类型添加到提供者列表(提供(AuthService),只需要AuthService执行相同操作).
如果要注入与请求的类不同的类,请使用useClass.

  1. @Injectable()
  2. export class MyService {
  3. constructor(private http: Http) {
  4. }
  5. }

如果您的提供商包含

  1. provide(Http,{useClass: HttpAdvanced});

然后MyService(它依赖于Http)会被注入HttpAdvanced.
确保在HTTP_PROVIDERS之后使用此行来覆盖HTTP_PROVIDERS中包含的默认Http提供程序.

如果DI本身不能解决依赖关系,因为它们不仅仅是其他提供者,那么使用useFactory.

正如刚才提到的,

Ensure you have this line after HTTP_PROVIDERS to override the default Http provider,contained in HTTP_PROVIDERS.

提供商列表中的顺序很重要.
当提供者列表包含多个类型的提供者时,则仅使用最后一个.

进口的顺序无关紧要.

一个文件中依赖类的顺序很重要,因为类没有被提升.

  1. export class ClassA {
  2. // constructor(private b: ClassB) {} // ClassB is unknown here
  3. constructor(@Inject(forwardRef(() => DataService)) {
  4. }
  5. }
  6.  
  7. export class ClassB {
  8. }

如果ClassB的代码高于ClassA,则不需要forwardRef().

另见Class is not injectable if it is defined right after a component with meta annotation

猜你在找的设计模式相关文章