首页 > 解决方案 > 如何在 Angular 6+ 中为库级接口的应用程序级具体实现定义可摇树的提供程序?

问题描述

我们目前正在使用 Angular 7。我已经阅读了 Angular 关于依赖注入和创建可摇树提供程序的指南。我已经阅读了十几个关于定义 InjectionTokens 或使用抽象类作为标记来为接口或抽象类提供具体类的问答和博客文章。但他们似乎都假设所有代码都在一个 Angular 项目中。

在我们的架构中,我有一个 Angular 库项目,其中包含我的接口和 InjectionToken:

export const MY_SERVICE = new InjectionToken<MyService>('my-service');

export interface MyService {
    someMethod();
}

在那个库项目中,我有一个指令可以注入这个令牌:

export class MyDirective {
    constructor(@Inject(MY_SERVICE) myService: MyService) { }

    @HostListener('click')
    private clicked() {
        this.myService.someMethod();
    }
}

我想在应用程序级别提供此服务的实际实现,这是另一个导入库项目的 Angular 项目。

Angular 应用程序项目将具有 MyService 的具体实现:

@Injectable({
    providedIn: 'root'
})
export class ConcreteMyService implements MyService {
    someMethod() {
        console.log('Application specific concrete implementation!');
    }
}

我之所以使用providedIn: 'root',是因为我读过的所有内容都表明这是使该树可摇动所必需的。问题是我不知道如何将它连接到 Angular 的 DI 系统以便在保持可摇树的同时ConcreteMyService注入。MyDirective

请记住,MyDirective并且与MyService处于不同的项目中ConcreteMyService,并且对此一无所知。这是设计使然,不应更改。

我提到这一点是因为我看到其他人建议在设置 InjectionToken 时执行以下操作:

export const MY_SERVICE = new InjectionToken<MyService>('my-service', {
    factory: () => new ConcreteMyService()
});

这里的问题是ConcreteMyService库项目中不可用,也不应该......这不是一个选项。

我见过的唯一似乎可以完成我所要求的解决方案是将提供程序添加到模块中,例如:

@NgModule({
    providers: [
        { provide: MY_SERVICE, useClass: ConcreteMyService }
    ]
})
export class SomeModule { }

但根据我所阅读的所有内容,这不是可摇树的。


如何使ConcreteMyServicetree-shakable 同时提供给 Angular DI 系统以便在MY_SERVICE请求我的令牌的情况下使用?请记住库与应用程序项目的分离。

标签: angulardependency-injectiontree-shaking

解决方案


推荐阅读