如何将派生的 class 作为服务注入

How do you inject a derived class as a service

我想将我的组件使用的服务接口与其实现分开(以简化有能力的手工模拟的创建,它发生了),并将实现作为使用它的组件的依赖项注入.这种方法在 Java Spring 后端很常见。

所以,如果我有这样的代码:

export abstract class AbstractMyService {// Defines the interface of the service
   ...
}

export class MyService extends AbstractMyService {// The concrete implementation
   ...
}

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

    constructor(
        private readonly service: AbstractMyService) {
    }

    ...
}

如何确保当 MyComponent 在应用程序中实例化时,它有一个 MyService 类型的对象传递给它的构造函数?

我知道如果我没有分离接口和实现(所以MyService是一个具体的class而AbstractMyService没有存在),我可以简单地这样做:

@Injectable({
    providedIn: 'root'
})
export class MyService {
   ...
}

我只需要将 MyService 注释为 @Injectable 吗?还是我必须做一些更复杂的事情?

您应该将实现声明为 提供者 显式

@NgModule({ // or @Component, depending on the place you want to configure.
....
  providers: [{ 
    provide: AbstractMyService,
    useClass: MyService
  }]
}) 

无法按照 Spring 中的方式进行“自动检测”。该配置明确表示,如果某些东西使用令牌 AbstractMyService 注入项目,class MyService 将用作构造函数。

在您希望所有组件使用相同的具体 class 的常见情况下,您可以为您的 AppModule 声明 provider。对于单元测试,您可以将提供程序声明为 TestBed 配置的一部分:

      TestBed.configureTestingModule({
         declarations: [MyComponent],
         providers: [
            ...
            { provide: AbstractMyService, useFactory: () => { return new MockMyService(...); } }]
        });