【问题标题】:Angular DI and inheritance: injecting extensions of a base serviceAngular DI 和继承:注入基础服务的扩展
【发布时间】:2019-02-26 13:07:33
【问题描述】:

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

@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')
  }
}

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

@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();

    }
}

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

Who's there?

speaking from BaseService

speaking from BaseService

speaking from BaseService
  • 为什么这不起作用?
  • 为什么 SomeService、AnotherService 和 BaseService 不是 Angular DI 的唯一标记?

好像放了

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

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

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

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

【问题讨论】:

  • 这只是 OOP 的概念
  • 想解释一下它是否如此简单? ;)
  • 您的评论毫无意义。如果您认为自己对 OP 问题有答案,请添加。

标签: javascript angular typescript inheritance dependency-injection


【解决方案1】:

SomeServiceAnotherServiceBaseService 继承装饰器元数据,因此 Angular 会在其位置注入 BaseService 的实例。

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

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

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');
  }
}

modified your plnkr来测试这个方法。

【讨论】:

  • 非常感谢!注意详细说明“这很危险......触发运行时错误”。 ?
  • 使用你原来的方法,如果你在AnotherService中定义anotherFoo()并在组件构造函数中调用它,就会出现异常。
  • 啊,是的,很明显。因为那时实际上没有AnotherService 的实例。另外,我认为“SomeServiceAnotherServiceBaseService 继承装饰器元数据”很奇怪(尽管我猜你是对的)。我想这与emitDecoratorData 在幕后的工作方式有关。派生类不应该有自己的元数据吗?
  • 我记得前段时间在角源中读到过,遗憾的是我找不到它。在那之前,不要认为我的回答是某种“绝对真理”:D
  • 正如我们所说,我实际上是在深入研究源代码以弄清楚这种元数据继承是如何精确工作的,但这让我很困惑。如果你重新发现了相关的代码行,请告诉我!
猜你喜欢
  • 2018-10-18
  • 2014-07-10
  • 1970-01-01
  • 2011-03-03
  • 1970-01-01
  • 2018-08-30
  • 2016-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多