有人可以解释何时使用useFactory而不是useClass?我已经看过ng2文档,我已经看过这些例子,但是我无法将它们映射到我的问题中.目前我的引导程序看起来像这样:
bootstrap( App,[ 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 }) ] );
我的最新一期是:
EXCEPTION: Error during instantiation of AuthService! (HeaderBar -> AuthService). ORIGINAL EXCEPTION: TypeError: this.http.get is not a function
我的依赖项就像
HttpAdvanced -> Http(ng2),MsgService MsgService -> MsgServiceInternal AuthService -> HttpAdvanced FormBuilderAdvanced -> FormBuilder(ng2),HttpAdvanced
1.我是否正确使用了provide / useClass / useFactory,我如何提供具有其他依赖关系的服务?
此外,我在我的代码中的一个地方:
static isUserInjector() { return (next,prev) => Injector.resolveAndCreate([AuthService,{ useClass: HttpAdvanced })]).get(AuthService).isUser(); }
因为我想拥有一个我提供的功能
@CanActivate(AuthService.isEditorInjector())
但是我不能使用构造函数注入,因为@CanActivate在类范围之外,所以我不能在控制器中注入服务然后引用像@CanActivate(this.authService.isEditor())
2.对此有什么好的解决方案?
一些代码:
@Component({ selector: 'ShowStats',templateUrl: './dest/views/showStats/showStats.html',directives: [ COMMON_DIRECTIVES,UsersCount,AdminsList,GlobalWishlist,PopularTrack ] }) export class ShowStats { authService : AuthService; constructor( authService : AuthService ){ this.authService = authService; } } ... next file ... @Injectable() export class HttpAdvanced { msgService: MsgService; http: Http; constructor(msgService: MsgService,http: Http) { this.msgService = msgService; this.http = http; } /* * This is for plain ol' GET requests .. with callback of course. */ public get(url,callback) { return this.http.get(url).subscribe((res) => { let data = res.json().data; callback(data); },this.msgService.httpErrorHandler); } .... other code for HttpAdvanced
3.
导入文件的顺序对DI是否重要?我想我注意到,因为我在同一个文件中有MsgService和MsgServiceInternal,并且MsgService依赖于Internal,我之前必须放置Internal但是我不是100%它是否与导入顺序相同?
4.
所以,如果我只是这样做:
bootstrap( App,MsgService,HttpAdvanced,AuthService,FormBuilderAdvanced,MsgServiceInternal ] );
我明白了:
Cannot resolve all parameters for 'FormBuilderAdvanced'(?,?). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'FormBuilderAdvanced' is decorated with Injectable.
我曾经用useFactory删除这个错误,但我现在很困惑.这是否意味着没有注入deps,因为它看不到它们或什么?
Form类:
export class FormBuilderAdvanced { http: HttpAdvanced; fb: FormBuilder; constructor(fb: FormBuilder,http: HttpAdvanced) { this.fb = fb; this.http = http; } create(controlNames: string[],submissionUrl: string,getter?: any) { return new Form(this.fb,this.http,controlNames,submissionUrl,getter); } }
bootstrap( App,// provide(MsgService,// is just fine when no special behavior is required // provide(HttpAdvanced,provide(Http,{useClass: HttpAdvanced}); AuthService,provide(FormBuilder,{ useClass: FormBuilderAdvanced}),MsgServiceInternal) ] );
如果要使类可用于注入,只需将类型添加到提供者列表(提供(AuthService),只需要AuthService执行相同操作).
如果要注入与请求的类不同的类,请使用useClass.
例
@Injectable() export class MyService { constructor(private http: Http) { } }
如果您的提供商包含
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 defaultHttp
provider,contained inHTTP_PROVIDERS
.
提供商列表中的顺序很重要.
当提供者列表包含多个类型的提供者时,则仅使用最后一个.
进口的顺序无关紧要.
一个文件中依赖类的顺序很重要,因为类没有被提升.
例
export class ClassA { // constructor(private b: ClassB) {} // ClassB is unknown here constructor(@Inject(forwardRef(() => DataService)) { } } export class ClassB { }
如果ClassB的代码高于ClassA,则不需要forwardRef().
另见Class is not injectable if it is defined right after a component with meta annotation