ANDRII DATSENKO <ASDatsenko@luxoft.com>
TECHNICAL LEAD
May 17, 2017
TAKE CONTROL OF DI
~Wikipedia
House
Bathroom
Kitchen
Garage
Car
Storage
class House {
private bathroom: Bathroom;
private garage: Garage;
private kitchen: Kitchen;
constructor() {
this.bathroom = new Bathroom();
this.garage = new Garage();
this.kitchen = new Kitchen();
}
}
// what else?...
class Garage {
private car: Car;
private storage: Storage;
constructor() {
this.car = new Car();
this.storage = new Storage();
}
}
Engine ?
Tools ?
// ...
class Garage {
private car: Car;
private storage: Storage;
constructor(car: Car, storage: Storage) {
this.car = car;
this.storage = storage;
}
}
class House {
constructor(private bathroom: Bathroom,
private garage: Garage,
private kitchen: Kitchen,
/* etc... */) {}
}
const house = new House(
new Bathroom(),
new Garage(new Car(), new Storage()),
new Kitchen()
);
Do we really need to know that?!
const injector = new Injector([
House,
Bathroom,
Garage,
Kitchen,
Car,
Storage
]);
const house = injector.get(House);
root injector
modules
components
configuration
const injector = ReflectiveInjector.resolveAndCreate([Garage, Car, Storage]);
const garage = injector.get(Garage);
// Done for you
platformBrowserDynamic().bootstrapModule(AppModule);
@NgModule({
imports: [
BrowserModule
],
declarations: [
AppComponent
],
providers: [
HomeService,
],
exports: [
BrowserModule
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
external providers
own providers
also a provider
re-export
import { Component } from '@angular/core';
import { HomeService } from './home.service';
@Component({
selector: 'app-home',
providers: [HomeService],
template: `
<h2>Home</h2>
`
})
export class HomeComponent {
constructor(homeService: HomeService) {
this.home = homeService.getHome();
}
}
own providers
import { Component } from '@angular/core';
import { HomeService } from './home.service';
import { SmartHomeService } from './smart-home.service';
@Component({
selector: 'app-home',
providers: [{
provide: HomeService,
useClass: SmartHomeService
}],
template: `<h2>Home</h2>`
})
export class HomeComponent {
constructor(homeService: HomeService) {
this.home = homeService.getHome();
}
}
override service
class
value
factory
@Injectable()
class HomeService {
constructor(private bathroom: Bathroom,
private kitchen: Kitchen,
private garage: Garage) {}
getHome() {
}
}
declare injection
providers: [ HomeService,
// Creates two instances of `HomeService`
{ provide: OldHomeService, useClass: HomeService}
]
providers: [ HomeService,
// alias to existing
{ provide: OldHomeService, useExisting: HomeService}
]
const defaultHome = <HomeService> {
getHome: () => { return {}; }
};
[{ provide: HomeService, useValue: defaultHome }]
Non-class values???
import { InjectionToken } from '@angular/core';
export let APP_CONFIG = new InjectionToken<AppConfig>('app.config');
export interface AppConfig {
apiHost: string;
}
export const appConfig: AppConfig = {
apiHost: 'api.some.com'
};
// Configure
providers: [{ provide: APP_CONFIG, useValue: appConfig}]
// Inject
constructor(@Inject(APP_CONFIG) config: AppConfig) {
this.title = config.title;
}
Non-class values
@Injectable()
export class HomeService {
constructor(private car: Car, public isOwner: boolean) { }
getCar() {
return this.isOwner ? this.car : null;
}
}
const homeServiceFactory = (userService: UserService) => {
return new HomeService(userService.user.isOwner);
};
export let homeServiceProvider = {
provide: HomeService,
useFactory: homeServiceFactory,
deps: [UserService]
};
@Component({
providers: [homeServiceProvider]
})
export class HomeComponent { }
@Optional()
@Host()
@SkipSelft()
`null` when provider not found
stop searching for provider
skip current injector
Q&A Time
ANDRII DATSENKO <ASDatsenko@luxoft.com>
TECHNICAL LEAD
May 17, 2017
TAKE CONTROL OF DI