有人可以解释何时使用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