Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Allow specifying providers inside @Injectable decorator #45832

Closed
Labels
area: coreIssues related to the framework runtimecore: di
Milestone
@Harpush

Description

@Harpush

Which @angular/* package(s) are relevant/related to the feature request?

core

Description

Currently providers can be provided only in component or module or root or etc.. but not inside other providers.

  • One issue is that one cannot create a provider which depends upon another provider privately.
  • Another issue is multiple instances of the same provider which are linked to the provider scope it is provided in.

An example of a case that currently suffer from those problems:

@Injectable()classCounterServiceimplementsOnDestroy{ngOnDestroy():void{}}constprimaryCounterToken=newInjectionToken<CounterService>('primaryCounterToken');constprimaryCounterProvider:Provider={provide:primaryCounterToken,useClass:CounterService,};constsecondaryCounterToken=newInjectionToken<CounterService>('secondaryCounterToken');constsecondaryCounterProvider:Provider={provide:secondaryCounterToken,useClass:CounterService,};@Injectable()classTwoCountersService{constructor(    @Inject(primaryCounterToken)primary:CounterService,    @Inject(secondaryCounterToken)secondary:CounterService){}}consttwoCountersProviders:Provider[]=[primaryCounterProvider,secondaryCounterProvider,TwoCountersService,];

In this caseCounterService has some logic but inTwoCountersService two instances of it are required. The solution here is usingInjectionToken to create two instances and inject them. The second issue mentioned above is yet to be seen in this example, but the first issue is.
Lets assume I want to use thisTwoCountersService in a component - I need to provide all three tokens in the component providers - hence thetwoCountersProviders array. Ideally I would like to just specifyTwoCountersService.

Now lets assume I want two instances ofTwoCountersService just like I wanted withCounterService. At this point I am stuck due to the second issue - as I actually need 4 instances ofCounterService which is not possible this way.
The only solution is using a factory provider:

constcounterFactoryToken=newInjectionToken<CounterService>('counterFactoryToken');constcounterFactoryProvider:Provider={provide:secondaryCounterToken,useFactory:()=>()=>newCounterService(),};@Injectable()classTwoCountersService{privateprimary=this.counterFactory();privatesecondary=this.counterFactory();constructor(    @Inject(counterFactoryToken)privatecounterFactory:()=>CounterService){}}// Two instances:constfirstTwoCountersToken=newInjectionToken<TwoCountersService>('firstTwoCountersToken');constfirstTwoCountersProvider:Provider={provide:firstTwoCountersToken,useClass:TwoCountersService,};constsecondTwoCountersToken=newInjectionToken<TwoCountersService>('secondTwoCountersToken');constsecondTwoCountersProvider:Provider={provide:secondTwoCountersToken,useClass:TwoCountersService,};

Now i can safely injectfirstTwoCountersToken andsecondTwoCountersToken and have two instances and get 4 new instances ofCounterService.
The first issue is even more apparent here - I need to provide now:counterFactoryProvider,firstTwoCountersProvider andsecondTwoCountersProvider and if there was a service injecting both - that service too.
The second issue is solved here.
But - I lose lifecycle methods (ngOnDestroy) this way which isn't what I wanted.

So instead of factory provider I need a service and manually handle lifecycle... something like:

@Injectable()exportclassCounterServiceFactory{privateregistry:CounterService[]=[];getNew(){constsrv=newCounterService();this.registry.push(srv);returnsrv;}ngOnDestroy():void{for(constsrvofthis.registry){srv.ngOnDestroy();}this.registry=[];}}

And I got it working withA LOT of code and roundabout issues to solve. It still requires annoyingly providing providers carefully and a factory service for every service.

Proposed solution

If it was possible to provide providers inside@Injectable - it could be solved nicely:

@Injectable()classCounterServiceimplementsOnDestroy{ngOnDestroy():void{}}constprimaryCounterToken=newInjectionToken<CounterService>('primaryCounterToken');constprimaryCounterProvider:Provider={provide:primaryCounterToken,useClass:CounterService,};constsecondaryCounterToken=newInjectionToken<CounterService>('secondaryCounterToken');constsecondaryCounterProvider:Provider={provide:secondaryCounterToken,useClass:CounterService,};@Injectable({providers:[primaryCounterProvider,secondaryCounterProvider]})classTwoCountersService{constructor(    @Inject(primaryCounterToken)primary:CounterService,    @Inject(secondaryCounterToken)secondary:CounterService){}}constfirstTwoCountersToken=newInjectionToken<TwoCountersService>('firstTwoCountersToken');constfirstTwoCountersProvider:Provider={provide:firstTwoCountersToken,useClass:TwoCountersService,};constsecondTwoCountersToken=newInjectionToken<TwoCountersService>('secondTwoCountersToken');constsecondTwoCountersProvider:Provider={provide:secondTwoCountersToken,useClass:TwoCountersService,};

Now if I needfirstTwoCountersProvider andsecondTwoCountersProvider - that's only what I provide and inject and all the different instances are handled automatically as providers provided in@Injectable are sharing the providing scope.
Even better if there was a service injecting both - I would just provide that service ONLY and inject it.

Alternatives considered

The long and complicated solution from above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: coreIssues related to the framework runtimecore: di

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp