Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have a base service and two inhering services:

@Injectable({ providedIn: 'root' })
export class BaseService {
  foo(src?: string){
    return `speaking from ${src || 'BaseService'}`;
  }
}


@Injectable({ providedIn: 'root' })
export class SomeService extends BaseService {
  foo(){
    return super.foo('SomeService')
  }
}

@Injectable({ providedIn: 'root' })
export class AnotherService extends BaseService {
  foo(){
    return super.foo('AnotherService')
  }
}

I wish to inject them in some component and retrieve instances of the three separate classes:

@Component({
    selector: 'my-app',
    template: `
        <div>
            <p>Who's there?</p>
            <p>{{ base }}</p>
            <p>{{ some }}</p>
            <p>{{ another }}</p>

        </div>
    `,
})
export class App {
    base: string;
    some: string;
    another: string;

    constructor(base: BaseService, some: SomeService, another: AnotherService) {
        this.base = base.foo();
        this.some = some.foo();
        this.another = another.foo();

    }
}

Instead, I get three instances of the same class (HTML output):

Who's there?

speaking from BaseService

speaking from BaseService

speaking from BaseService
  • Why doesn't this work?
  • Why are SomeService, AnotherService and BaseService not unique tokens for Angular DI?

It seems that putting

...    
{ provide: SomeService , useClass: SomeService },
{ provide: AnotherService , useClass: AnotherService },
...

in the providers will make it work.

  • Why is this explicitly needed?

A plnkr: https://next.plnkr.co/edit/BvmppLHRbFbz9CFZ

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
244 views
Welcome To Ask or Share your Answers For Others

1 Answer

SomeService and AnotherService inherit the decorator metadata from BaseService, so angular injects an instance of BaseService in their place.

This is dangerous, as calling any instance member from either SomeService or AnotherService which isnt inherited from BaseService will trigger a run-time error.

The simplest way to archive the behavior you are looking for, would be to inherit from a common abstract base class, with no decorator:

export abstract class AbstractBaseService {
  foo(src?: string) {
    return `speaking from ${src || 'AbstractBaseService'}`;
  }
}

@Injectable({ providedIn: 'root' })
export class BaseService extends AbstractBaseService {
  foo() {
    return super.foo('BaseService');
  }
}

@Injectable({ providedIn: 'root'})
export class SomeService extends AbstractBaseService {
  foo() {
    return super.foo('SomeService');
  }
}

@Injectable({ providedIn: 'root' })
export class AnotherService extends AbstractBaseService {
  foo() {
    return super.foo('AnotherService');
  }
}

I modified your plnkr to test this approach.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...