web-dev-qa-db-fra.com

comment étendre le service avec des dépendances dans angular 2

J'ai un service parent qui a des dépendances comme

@Injectable()
export class ParentService{
  constructor(private http:Http, private customService:CustomService){}
}

et je veux étendre le service

@Injectable()
export class ChildService extends ParentService{
  constructor (){
    super(??) <= TypeScript now asking to enter two parameters according to ParentServie's constructor
  }
}

Modifier -----------------

@Injectable()
export class ParentService{
  constructor(private http:Http, private customService:CustomService){}
  get(){this.http.get(...)}
}

@Injectable()
export class ChildService extends ParentService{
  constructor (private http:Http, private customService:CustomService){
    super(http, customService)
  }
}

Ensuite, je peux utiliser dans les composants?

export class Cmp {
  constructor(private childService:ChildService){
    this.childService.get()
  }
}
24
Han Che

Les paramètres de la super classe doivent être répétés et transmis au super appel:

@Injectable()
export class ChildService extends ParentService{
  constructor (http:Http, customService:CustomService){
    super(http, customService);
  }
}

Il y a quelques "hacks" à contourner comme Inheritance and dependency injection

21
Günter Zöchbauer

Faites simplement le service de base ... non -@Injectable()! Par exemple, vous devez fournir une méthode pour récupérer le profil utilisateur dans LoginService. Cette méthode sera différente pour différentes instances de LoginService, et la classe parente ne doit rien savoir d'où vient cette méthode: il peut s'agir de lambda, il peut être une fonction exportée, il peut s'agir d'une méthode d'un autre service. Pour ce faire, vous pouvez déclarer le service parent quel service parent:

// Don't annotate it with @Injectable() ! It's a simple class.
export abstract class BaseLoginService {
  constructor(
    // This won't be injected automatically, 
    // child class must call super() and provide value for this argument.
    // Note: it's private, can't be accessed outside of BaseLoginService class
    private http: HttpClient,
    // Method used to retrieve user profile
    private profileGetter: () => Observable<UserDetails>, 
    private router: Router
  ) {
    this.profileGetter().subscribe(); // Do something with this method
  }

Ensuite, étendez-le dans la classe enfant:

// Child class must be annotated with @Injectable(),
// if you don't need to extend it further
@Injectable() 
export class LoginService extends BaseLoginService {

  constructor(
    // Note: no public/private/protected here - "http"
    // will be just an argument
    http: HttpClient, 
    private profileService: ProfileService, // This is the private field of LoginService class
    router: Router,
    // Some service used by LoginService class, parent class BaseLoginService
    // doesn't need to know about SomeOtherService
    private someOtherService: SomeOtherService
  ) {
    super(
      http,
      // Need lambda here to capture profileService instance. If
      // profileService.getUserDetailsMethod doesn't use instance
      // fields or methods, then we can simply write 
      // "profileService.getUserDetailsMethod" (without quotes, obviously).
      () => profileService.getUserDetailsMethod(), 
      router
    );
    this.someOtherService.doSomething(); // Custom initialization code
  }

Remarque: dans la section providers du module, spécifiez LoginService au lieu du parent BaseLoginService:

providers: [
  LoginService,

et l'utiliser dans les classes de composants:

export class LoginComponent implements OnInit {
  constructor(
    private loginService: LoginService
  ) {
  }

Si vous devez utiliser le service parent (par exemple dans les composants partagés qui n'ont besoin que de fonctionnalités de la classe de service parent), fournissez BaseLoginService de cette façon:

providers: [
  {provide: BaseLoginService, useExisting: LoginService}, // For those components which need functionality from base class only
  LoginService, // Still need this one for those components which need functionality from child class
16
izogfif

Si vous créez les services DI dans la classe abstraite protected et omettez le constructeur dans la sous-classe, alors les services sont disponibles dans la sous-classe.

0
Joey Gough