【问题标题】:Angular Inheritance Inject Different InstancesAngular 继承注入不同的实例
【发布时间】:2019-02-10 08:08:36
【问题描述】:

我有 2 个彼此相同的组件。唯一的区别是它们的名称和一些 html 标头。因此,我想使用继承。

我创建了一个抽象服务:

export abstract class AbstractFilmListService {

  protected readonly API = WebUtils.RESOURCE_HOST_API + 'film/';


  constructor(protected client: HttpClient) {
  }

  deleteFilm(filmId: number) {
    return this.client.delete(this.API + filmId);
  }

  fetchFilms(): Observable<Film[]> {
    return this.client.get(this.API) as Observable<Film[]>;
  }
}

子类 1:

@Injectable({
  providedIn: 'root'
})
export class FilmListService extends AbstractFilmListService {
  constructor(protected client: HttpClient) {
    super(client);
  }
}

子类 2:

@Injectable({
  providedIn: 'root'
})
export class SeriesListService extends AbstractFilmListService{

  protected readonly API: string;

  constructor(client: HttpClient) {
    super(client);
    this.API = WebUtils.SERIES_API;
  }
}

到目前为止,一切都很好。但我想对组件做同样的事情:

电影列表组件:

@Component({
  selector: 'app-film-list',
  templateUrl: './film-list.component.html',
  styleUrls: ['./film-list.component.css']
})
export class FilmListComponent implements OnInit {

  constructor(protected client: HttpClient,
              protected router: Router,
              protected snackService: SnackService,
              protected filmListService: FilmListService // <- Problem is here !
              ) {
  }
//....

}

系列列表组件:

 @Component({
  selector: 'app-series-list',
  templateUrl: './series-list.component.html',
  styleUrls: ['./series-list.component.css']
})
export class SeriesListComponent extends FilmListComponent implements OnInit {

  constructor(protected client: HttpClient,
              protected router: Router,
              protected snackService: SnackService,
              protected filmListService: FilmListService // <- Problem is here!
  ) {
    super(client, router, snackService, filmListService);
  }

  ngOnInit() {
  }

}

我想FilmListComponent 声明AbstractFilmListService 而不是FilmListService,当它开始注入服务时,它应该注入FilmListService

同样的方式SeriesListComponent 应该声明AbstractFilmListService 而不是FilmListService,当它开始注入服务时它应该注入SeriesListService

我的意思是这样的:

export class FilmListComponent implements OnInit {

  constructor(
             // ...
              protected filmListService: AbstractFilmListService
              ) {
          this.filmListService = new FilmListService(); // Angular should do  something like this...
  }
//....

}

SeriesListComponent 也一样:

export class SeriesListComponent implements OnInit {

  constructor(
             // ...
              protected filmListService: AbstractFilmListService
              ) {
          this.filmListService = new SeriesListService(); // Angular should do  something like this...
  }
//....

}

我知道 Angular 不会为每个使用单例设计模式进行依赖注入的组件创建新的服务。为了说明我自己写了

"new SeriesListService(), new FilmListService()"

如何为不同的组件注入不同的实例,即使它们的类型在构造函数中声明相同?


更新

应用模块:

@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    HeaderComponent,
    HomeComponent,
    UserManagementComponent,
    ActorComponent,
    FilmComponent,
    SeriesComponent,
    ProductComponent,
    SafeUrlPipe,
    FilmListComponent,
    HeroComponent,
    CoverComponent,
    SeasonComponent,
    ChapterComponent,
    SeriesListComponent,
    ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpClientModule,
    RoutingModule,
    TokenModule,
    MaterialModule,
    NgbTimepickerModule,
    HttpInterceptorModule
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {
}

【问题讨论】:

  • 这取决于您在哪里提供服务。您可以像这样提供其中一个:providers: [ { provide: AbstractFilmListService, useClass: SeriesListService } ],但如果它们在同一个模块中提供,那么第二个提供的服务将覆盖第一个。您似乎想使用AbstractFilmListService 作为注入令牌。我可以看看您提供服务的模块吗?
  • 我当然要添加我的模块。

标签: javascript angular typescript dependency-injection singleton


【解决方案1】:

如果它不是一个单例服务,那么在我看来使用providedIn 没有多大意义。

但要回答您的问题,如果您想要此服务的不同实例,您应该在 @Component 注释中提供该服务:

@Component({
  selector: 'app-series-list',
  templateUrl: './series-list.component.html',
  styleUrls: ['./series-list.component.css'],
  providers: [AbstractFilmListService] // <-- will create a new instance for this component
})

【讨论】:

  • 或许应该是:providers: [ { provide: AbstractFilmListService, useClass: SeriesListService } ],因为只要提供AbstractFilmListService就会创建一个抽象类的实例(不是说抽象类可以实例化),但是他想注入一个具体的派生类,虽然我可能错了。
  • @Wingnod 啊谢谢,我读起来有点懒,我必须承认 :-) 只是想给出关于分层 DI 的主要思想
  • 没问题!除了那一点,我也认为这是解决他问题的最佳方法:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-30
  • 2017-05-24
相关资源
最近更新 更多