Professional Documents
Culture Documents
08 Dependency Injectionand Providers
08 Dependency Injectionand Providers
class Account {
//tight coupling
logger: Logger = new Logger();
}
class Account {
//loose coupling
constructor(public logger: Logger) {}
}
Dependency Injection Framework
The Injector
– Gets a list of registered classes
– Manages the responsibility of dependency creation
– Supplies the dependency to the dependent object
This makes sure that Logger is created and injected into the Account
constructor
Dependency Injection in Angular
Angular's Dependency Injection mechanism
– A Component simply has to ask for a service
– An Injector is responsible for delivering the service and managing its life cycle
– The Injector relies on Providers
– Providers can create or return a service
Three Steps
The service
The client
@Component({
providers: [AuthenticationService] Register Service
})
export class Login {
constructor(private _authenticationService: AuthenticationService){}
}
Use Service
Service Registration (Angular 6+)
Registration can be handled inside the @Injectable decorator
@Injectable({
providedIn: 'root'
})
@Injectable()
export class GameService {
getGames() { return GAMES; }
}
Register the Service
Register the service with the injector
– In a module application-wide
– In a component locally
// In a module // In a component
@NgModule({ @Component({
providers: [GameService] selector: 'my-games',
}) template: `
export class AppModule { } <h2>Games</h2>
<game-list></game-list>
`,
providers: [GameService]
})
Using the Service
Create a constructor in the component in-need
– Make sure that it has a correct type annotation!
@Component({
...
})
export class GameListComponent {
games : Game[];
constructor( private _gameService: GameService) {
this.games = _gameService.getGames();
}
}
Optional Service
By default every service needs to be registered
C DI
C C DI DI
C C C DI DI DI
Hierarchical Injection
When registered in a component, the singleton can be injected into the
component and all its children
C1 Register here
C2 C3
Use here
C4 C4 C4
@NgModule({
imports: [BrowserModule],
declarations: [AppComponent, GameListComponent, GameDetailComponent],
bootstrap: [AppComponent],
providers: [LoggerService]
})
export class AppModule { }
Where to Register?
Stateless Services can easily be shared
– One instance for all!
– Remember that you can
register when bootstrapping
providers: [NewLogger,
// Not aliased! Creates two instances of
`NewLogger`
{ provide: OldLogger, useClass: NewLogger
})],
Hmm, doesn't seem to work as requested... Solution?
providers: [NewLogger,
// Alias OldLogger w/ reference to
NewLogger
{ provide: OldLogger, useExisting:
NewLogger })],
Factory Provider
What if the right providers needs to be decided at runtime?
– And even needs to switch at runtime
Example
– GameService hides the alpha games from normal users, but people can switch roles in
one browser session
Solution
– Use a factory provider
Factory Provider
TS
let gameServiceFactory = (logger: LoggerService, userService: UserService) => {
return new SecureGameService(logger, userService.user.isAuthorized);
};
@Component({
providers: [{
provide: GameService,
useFactory: gameServiceFactory,
deps: [LoggerService, UserService]
//deps are here as provider tokens to be able to inject
//the correct services
}]
})
Providers
For the sake of encapsulation, you can separate the Provider declaration from
the component
export let GameServiceProvider: FactoryProvider = {
provide: GameService,
useFactory: gameServiceFactory,
deps: [LoggerService, UserService]
};
@Component({
providers: [GameServiceProvider, UserService, ...]
})
Providing Multiple Dependencies
Using multi extends a value rather than overriding it
– Receive array instead of one item
Example
– Return a collection of validator functions
Dependency Injection Tokens
Registering a provider needs a token
– Injector maintains internal token-provider map with token as key
Alternatives
– String tokens
– Injectiontokens
Interfaces as a Token?
Injecting configuration objects with a value provider
– A token is needed, but what to use?