Search code examples
angulardependency-injectionionic2

Angular 2 Dependency Injection singleton / new instances


I am trying to wire up DI on angular2. I basically have all my services which I expect to be singletons in the providers array in my app.module.ts.

providers: [
    { provide: ErrorHandler, useClass: IonicErrorHandler },
    { provide: 'ICommentService', useClass: CommentService },
    { provide: 'IPostService', useClass: PostService },
    { provide: 'IQueryParamsService', useClass: QueryParamsService },
    { provide: 'IUserService', useClass: UserService },
    { provide: 'IInjectorService', useClass: InjectorService},
    { provide: 'IPostFactory', useClass: PostFactory}
]

I also want to have a ReflectiveInjector that will be in charge of creating instances of objects I need. I created it like this:

this.injector = ReflectiveInjector.resolveAndCreate([
   { provide: 'IComment', useClass: Comment },
   { provide: 'ICommentList', useClass: CommentList },
   { provide: 'IPic', useClass: Pic },
   { provide: 'IPost', useClass: Post },
   { provide: 'IUser', useClass: User }            
]);

My issue is that for example Post requires a PostService and when I ask this injector for a Post it errors out because it can't find the PostService, which makes sense because it's separate injector trees.

I ask the injector like this:

this.injector.get('IPost');

This is part of my Post class:

@Injectable()
export class Post extends DBObject implements IPost{
    private title: string;
    private body:string;
    //private comments:ICommentList;
    //private img:IPic;
    //private author:IUser;
    private authorId: number;
    private date:Date;

    constructor(
        @Inject('IPostService') private PostService:IPostService,
        @Inject('IUserService') private UserService:IUserService,
        @Inject('IUser') private author:IUser,
        @Inject('IPic') private img: IPic,
        @Inject('ICommentList') private comments:ICommentList
    ){
        super();
    }

I omitted irrelevant functions. I expect IPostService, IUserService to be the singleton declared in the module but IUser, IPic and ICommentList should be new instances every time.

The error is:

Error in ./TabsPage class TabsPage - caused by: No provider for IPostService! (IPost -> IPostService)

How can I accomplish this?

Thanks!

PS: This is an angular problem but I'm using Ionic in case it matters.


Solution

  • You probably want

    constructor(injector:Injector) {
      resolvedProviders = ReflectiveInjector.resolve([
       { provide: 'IComment', useClass: Comment },
       { provide: 'ICommentList', useClass: CommentList },
       { provide: 'IPic', useClass: Pic },
       { provide: 'IPost', useClass: Post },
       { provide: 'IUser', useClass: User }            
      ]);
      let this.injector = ReflectiveInjector.fromResolvedProviders(resolvedProviders, injector);
    

    Multiple calls to

    this.injector.get('IPost');
    

    will get you the same Post instance though.

    Angular2 DI maintains a single instance per provider. If you want to get a different instance for each call, you can provide a factory, get this factory from DI and call the factory to get a new instance. If you need more details on this approach leave a comment.

    See also