【问题标题】:How to change Angular service injection instance如何更改 Angular 服务注入实例
【发布时间】:2021-02-04 19:07:46
【问题描述】:

您好,我正在尝试更改组件树的注入服务实例(父级,例如ParentComponent 和一些子级,例如Child1ComponentChild2Component),它们都依赖于名为DataService 的服务。但是根据路由,例如/demo,我想向ParentComponent 及其子代注入另一个服务实例(它将派生自接口/抽象类,这不是问题)并且不更改@ 的内部实现987654327@ 或 Child1ComponentChild2Component 让他们使用 MockDataService 构造函数注入服务。

有什么想法吗?我需要一些可以在没有工厂方法的情况下即时更改注入的东西。

abstract class AbstractDataService {}

@Inject()
class DataService extends AbstractDataService {}

@Inject()
class MockDataService extends AbstractDataService {}

@Component({
  selector: 'app-root'
  template: '<app-parent></app-parent>'
})
class AppComponent implements OnInit {
  constructor(private router: Router) { }

  ngOnInit() {
    this.router.events.subscribe((evt: NavigationStart) => {
      if (evt.url === '/demo') { // something like that or do it in router config...
        // TODO change the injection instance here for ParentComponent and children...
      }
    });
  }
}

@Component({
  selector: 'app-parent',
  template: '<app-child1></app-child1> <app-child2></app-child2>'
})
class ParentComponent {
  constructor(private data: AbstractDataService) { }
  // ...
}


@Component({...})
class Child1Component {
  constructor(private data: AbstractDataService) { }
  // ...
}


@Component({...})
class Child2Component {
  constructor(private data: AbstractDataService) { }
  // ...
}

(我正在使用 Angular 10 顺便说一句)

【问题讨论】:

    标签: angular dependency-injection inject


    【解决方案1】:

    如果你没有状态管理并且想要没有工厂,也许你可以创建一个服务而不是规则它们,你可以使用 rxjs BehaviorSubject 改进方式

    abstract class AbstractDataService {}
    
    @Inject()
    class DataService extends AbstractDataService {}
    
    @Inject()
    class MockDataService extends AbstractDataService {}
    
    @Inject({
      providedIn: 'root',
    })
    class DataStoreService {
    
    service = this.dataService;
    
    constructor(private dataService: DataService, private mockDataService: MockDataService){}
    
    useDemoService(){
      this.service = this.mockDataService;
    }
    
    useRealDataService(){
      this.service = this.dataService;
    }
    
    anyMethod(){
    return this.service.getAnyValue();
    }
    
    }
    
    @Component({
      selector: 'app-root'
      template: '<app-parent></app-parent>'
    })
    class AppComponent implements OnInit {
      constructor(private router: Router, private dataStoreService: DataStoreService) { }
    
      ngOnInit() {
        this.router.events.subscribe((evt: NavigationStart) => {
          if (evt.url === '/demo') {
           dataStoreService.useDemoService();
          }else{
           dataStoreService.useRealDataService()
          }
        });
      }
    }
    
    @Component({
      selector: 'app-parent',
      template: '<app-child1></app-child1> <app-child2></app-child2>'
    })
    class ParentComponent {
      constructor(private data: DataStoreService) { }
      // ...
    }
    
    
    @Component({...})
    class Child1Component {
      constructor(private data: DataStoreService) { }
      // ...
    }
    
    
    @Component({...})
    class Child2Component {
      constructor(private data: DataStoreService) { }
      // ...
    }
    

    【讨论】:

    • 这是一个很好的解决方法。我不反对工厂,但我不知道它是否会做我想要的。我正在寻找关于Injector 的无证框架知识,什么不是。否则,我可以将 if 语句全部覆盖并完成。
    猜你喜欢
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    • 2018-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-20
    相关资源
    最近更新 更多