Angular DI 和继承:注入基础服务的扩展 [英] Angular DI and inheritance: injecting extensions of a base service

查看:23
本文介绍了Angular DI 和继承:注入基础服务的扩展的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基本服务和两个继承服务:

@Injectable({ providedIn: 'root' })导出类 BaseService {foo(src?: 字符串){从 ${src || 返回`'基础服务'}`;}}@Injectable({providedIn: 'root' })导出类 SomeService 扩展了 BaseService {富(){return super.foo('SomeService')}}@Injectable({providedIn: 'root' })导出类另一个服务扩展了 BaseService {富(){return super.foo('AnotherService')}}

我希望将它们注入某个组件并检索三个独立类的实例:

@Component({选择器:'我的应用',模板:`<div><p>谁在那里?</p><p>{{ base }}</p><p>{{一些}}</p><p>{{另一个}}</p>

`,})出口类应用{基础:字​​符串;一些:字符串;另一个:字符串;构造函数(基础:BaseService,一些:SomeService,另一个:AnotherService){this.base = base.foo();this.some = some.foo();this.another = another.foo();}}

相反,我得到了同一个类的三个实例(HTML 输出):

谁在那里?来自 BaseService来自 BaseService来自 BaseService

  • 为什么这不起作用?
  • 为什么 SomeService、AnotherService 和 BaseService 不是 Angular DI 的唯一令牌?

好像放了

<代码>...{ 提供: SomeService , useClass: SomeService },{提供:AnotherService,useClass:AnotherService},...

在提供程序中将使其工作.

  • 为什么明确需要这样做?

一个 plnkr:https://next.plnkr.co/edit/BvmppLHRbFbz9CFZ

解决方案

SomeServiceAnotherService 继承了 BaseService 的装饰器元数据,所以 angular在它们的位置注入 BaseService 的一个实例.

这是危险的,因为从 SomeServiceAnotherService 调用任何不是从 BaseService 继承的实例成员都会触发运行时错误.

归档您正在寻找的行为的最简单方法是从公共抽象基类继承,没有装饰器:

导出抽象类 AbstractBaseService {foo(src?: 字符串) {从 ${src || 返回`'AbstractBaseService'}`;}}@Injectable({providedIn: 'root' })导出类 BaseService 扩展 AbstractBaseService {富(){return super.foo('BaseService');}}@Injectable({providedIn: 'root'})导出类 SomeService 扩展 AbstractBaseService {富(){return super.foo('SomeService');}}@Injectable({providedIn: 'root' })导出类 AnotherService 扩展 AbstractBaseService {富(){return super.foo('AnotherService');}}

修改了您的 plnkr 以测试这种方法.

I have a base service and two inhering services:

@Injectable({ providedIn: 'root' })
export class BaseService {
  foo(src?: string){
    return `speaking from ${src || 'BaseService'}`;
  }
}


@Injectable({ providedIn: 'root' })
export class SomeService extends BaseService {
  foo(){
    return super.foo('SomeService')
  }
}

@Injectable({ providedIn: 'root' })
export class AnotherService extends BaseService {
  foo(){
    return super.foo('AnotherService')
  }
}

I wish to inject them in some component and retrieve instances of the three separate classes:

@Component({
    selector: 'my-app',
    template: `
        <div>
            <p>Who's there?</p>
            <p>{{ base }}</p>
            <p>{{ some }}</p>
            <p>{{ another }}</p>

        </div>
    `,
})
export class App {
    base: string;
    some: string;
    another: string;

    constructor(base: BaseService, some: SomeService, another: AnotherService) {
        this.base = base.foo();
        this.some = some.foo();
        this.another = another.foo();

    }
}

Instead, I get three instances of the same class (HTML output):

Who's there?

speaking from BaseService

speaking from BaseService

speaking from BaseService

  • Why doesn't this work?
  • Why are SomeService, AnotherService and BaseService not unique tokens for Angular DI?

It seems that putting

...    
{ provide: SomeService , useClass: SomeService },
{ provide: AnotherService , useClass: AnotherService },
...

in the providers will make it work.

  • Why is this explicitly needed?

A plnkr: https://next.plnkr.co/edit/BvmppLHRbFbz9CFZ

解决方案

SomeService and AnotherService inherit the decorator metadata from BaseService, so angular injects an instance of BaseService in their place.

This is dangerous, as calling any instance member from either SomeService or AnotherService which isnt inherited from BaseService will trigger a run-time error.

The simplest way to archive the behavior you are looking for, would be to inherit from a common abstract base class, with no decorator:

export abstract class AbstractBaseService {
  foo(src?: string) {
    return `speaking from ${src || 'AbstractBaseService'}`;
  }
}

@Injectable({ providedIn: 'root' })
export class BaseService extends AbstractBaseService {
  foo() {
    return super.foo('BaseService');
  }
}

@Injectable({ providedIn: 'root'})
export class SomeService extends AbstractBaseService {
  foo() {
    return super.foo('SomeService');
  }
}

@Injectable({ providedIn: 'root' })
export class AnotherService extends AbstractBaseService {
  foo() {
    return super.foo('AnotherService');
  }
}

I modified your plnkr to test this approach.

这篇关于Angular DI 和继承:注入基础服务的扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆