【问题标题】:How to use @Inject and get the instance of the service not in the constructor?如何使用@Inject 并获取不在构造函数中的服务实例?
【发布时间】:2020-12-13 11:36:53
【问题描述】:

我有一个在其中使用 http 的通用类:

export abstract class GenericCrudService<T> {
  constructor(protected http: HttpService, protected resourse: Resourse) {}

  private entities: T[] = [];
  entitiesChanged$: Subject<T[]> = new Subject();

  getAllEntities() {
    this.http.get<T>(environment.endpoint + this.resourse).subscribe((res) => {
      this.entities = res;
      this.entitiesChanged$.next(this.entities);
    });
  }

  createEntity(entity: T) {
    return this.http
      .post(environment.endpoint + this.resourse, entity)
      .subscribe((_) => {
        this.entities.push(entity);
        this.entitiesChanged$.next(this.entities);
      });
  }
  deleteEntity(id: string) {
    return this.http
      .delete(environment.endpoint + this.resourse, id)
      .subscribe((res: any) => {
        this.entities = this.entities.filter((e: any) => e._id !== res.deleted);
        this.entitiesChanged$.next(this.entities);
      });
  }

  updateEntity(id: string, newEntity: T) {
    return this.http
      .put(environment.endpoint + this.resourse, id, newEntity)
      .subscribe((res: any) => {
        const updatedIndex = this.entities.findIndex(
          (e: any) => e._id === res.updated
        );
        this.entities[updatedIndex] = newEntity;
        this.entitiesChanged$.next(this.entities);
      });
  }

  getLatestEntities() {
    return this.entitiesChanged$.asObservable();
  }
}

还有扩展该类的服务:

@Injectable({
  providedIn: "root",
})
export class ExerciseService extends GenericCrudService<IExercise> {
  constructor(http: HttpService) {
    super(http, Resourse.exercise);
  }
}

我认为最好不要在练习服务中注入 http 客户端,因为它不需要它,并且只通过执行以下操作在通用客户端中创建它:

@Inject(HTTP_TOKEN?) http : HttpService 并在服务的任何地方使用 this.http。我的问题是,是否有可能并被推荐,如果可以,我怎样才能获得 HttpService 注入令牌,或者如果它不存在,我该如何创建一个?

【问题讨论】:

  • JFYI: resourse = Resourse.exercise; 行是多余的,因为它已经在父级中完成。在您的版本中,“分配”逻辑只是重复了。
  • 是不是弄错了
  • @Andrei 那么您对这段代码的重构有何建议?

标签: angular dependency-injection


【解决方案1】:

只有一种“优雅”的方式可以在 Angular 中注入任何东西,那就是构造方法。另一种方法是在构造函数中注入 Injector 并在运行时的任何时刻注入 Injector.get(token)。

myService = this.injector.get(MyService);
constructor(private injector: Injector) {}

在你的代码中

export abstract class GenericCrudService<T> {
  protected http = this.injector.get(HttpService);
  constructor(protected injector: Injector, protected resourse: Resourse) {}
...
}
....
export class ExerciseService extends GenericCrudService<IExercise> {
  constructor(injector: Injector) {
    super(injector, Resourse.exercise);
  }
}

那么在任何后代中,您只会将注入器传递给父级,并且父级可以在此注入器的帮助下注入任何它想要的东西

【讨论】:

  • 所以像我做的那样做比@Inject(HTTP_TOKEN?) http : HttpService 在服务中更好的做法?如果我扩展了两个以上的级别怎么办?你认为这样传递依赖是否正确?
  • 如果讨论是关于组件的,您可以使用角度 DI,因为它们具有组件级注入器。可以@Component({... providers: [provide: Resource, useValue: Resource.excercise]}) class MyClass {};但遗憾的是,服务无法做到这一点。如果您有多级继承的计划,那么我会在构造函数中使用 Injector,然后在父级中注入任何需要的东西。如果您想在“父”级别之一添加依赖项,那就更好了。除了 1 个类之外,不需要其他更新。
  • 你能告诉我这是如何在我的代码中实现的吗?
  • 感谢您的帮助?
猜你喜欢
  • 1970-01-01
  • 2015-07-15
  • 2010-11-19
  • 2021-02-25
  • 1970-01-01
  • 2021-10-07
  • 1970-01-01
  • 1970-01-01
  • 2017-05-20
相关资源
最近更新 更多