Angular 角度:扩展服务和传递参数

Angular 角度:扩展服务和传递参数,angular,typescript,Angular,Typescript,我很难理解如何在Angular中扩展服务 我有一个连接到Firebase并执行各种常见任务(获取、设置、更新、列表等)的服务,我没有为我的特殊组件重新编写它,而是尝试扩展它 我的想法是,我可以只通过路径的新部分,但这会抛出一个错误: Cannot resolve all parameters for 'FirebaseService'(?). Make sure that all the parameters are decorated with Inject or have valid typ

我很难理解如何在Angular中扩展服务

我有一个连接到Firebase并执行各种常见任务(获取、设置、更新、列表等)的服务,我没有为我的特殊组件重新编写它,而是尝试扩展它

我的想法是,我可以只通过路径的新部分,但这会抛出一个错误:

Cannot resolve all parameters for 'FirebaseService'(?). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'FirebaseService' is decorated with Injectable.
问题在于构造函数和我缺乏面向对象的头脑。我可以将其他服务或提供者传递到我的服务中,但我不能再传递简单的字符串参数,除非我遗漏了什么。我尝试设置属性,但我认为我没有正确理解上下文

我想这是@Injectable的问题,但我不确定

以下是我第一次尝试的简化版本:

更新以包含PLUNKER链接:

我希望它能附上“项目”一行。没有,只是重复

然后我试着通过构造函数:

这会把一切都搞砸。我有办法解决这个问题,但这似乎是一个彻底的黑客


将“projects”参数传递给父类的正确方法是什么?

更新:如果您想使用标准服务接口而不需要手动实例化,并将简单值传递给构造函数,那么文档建议设置一个工厂,这几乎需要大量的代码: (向下滚动到Factory Providers)

下面的代码工作正常,但未将提供程序系统用于服务:

//things.service.ts
@Injectable()
export class ThingService {
  public myString: string = "base";
  constructor(str: string) {
    this.myString = str;
  }
}

@Injectable()
export class Thing2Service extends ThingService {
  constructor(){
    super('I AM CHILD');
  }
}

//app.component.ts
public thingService: ThingService = new ThingService("I AM PARENT");
public thing2Service: Thing2Service = new Thing2Service();

ThingService.myString === "I AM PARENT"; //true
Thing2Service.myString === "I AM CHILD"; //true

因此,在白金汉做了一些出色的工作之后,我决定用“典型”的方式做这件事是不可能的

Angular2简单地用注入器接管构造函数()函数。然而,真正起作用的是生成一个备用的“init”函数,然后您可以将参数传递给它

@Injectable()
export class ParentService {
  root:string = "This content comes from: ";
  myString:string = "The Parent";
  resultString:string;
  constructor(){
    this.init();
  }
  init() {
    this.resultString = this.root + this.myString;
  }
}


@Injectable()
export class ChildService extends ParentService {
  constructor(){
    super();
  }
  init() {
    this.myString = "The Child";
    super.init();
  }
}
通过这种方式,您可以在子对象上设置值或将其传递给父对象


这里是另一种扩展angular2服务的方法,它与DI一起工作。子服务不能为父服务使用的可注入服务使用相同的参数名,因此需要另一个HTTP参数名

父服务:

@Injectable()
export class GenericStore {
   ....
   constructor(public config:GenericConfig,private http:Http) {
        ....
   }
   ....
}
儿童服务:

const DEFAULT_CONFIG:GenericConfig = { ... };
@Injectable()
export class ConfigStore extends GenericStore {
   ....
   constructor(private anotherHttp:Http) {
        super(DEFAULT_CONFIG,anotherHttp);
   }
   ....
}

IMO最好的方法是使用抽象属性。这样,扩展类将被强制提供必要的值

abstract class GenericStore{

  abstract configVal: string;

  constructor(){}

  someMethod(){
    console.log('The config value is:', this.configVal);
  }
}

class UserStore extends GenericStore{

  configVal = 'A config value. Typescript will yell if not provided.'; 

  constructor(){
    super();
  }
}

我认为您对OOP的理解很好,只是angular2在依赖注入方面做了一些聪明但古怪的事情,所以注入/注入需要额外的语法。我将从这里开始:CH,是的,我看到了这一点,将服务注入彼此和组件是完全有意义的。我要做的是在构造函数中传递一个参数,或者从一个子元素传递给一个父元素。在常规的ES6类中,这两种方法似乎都是可能的,但对于Angular DI,它会吃掉它们,我不确定为什么..这段代码适用于常规的Javascript对象,但不适用于Angular 2服务。这是一个具有传递属性的plunker:,这是一个具有您建议的构造函数的plunker。它爆炸了:我正在运行我的答案中查看上面的代码,一模一样。因此,您在编译步骤中遗漏了一些内容,或者出现了一些错误。哦,我明白您的意思。我将服务实例化为类,而不是通过注入器,即使它们已被@Injectable修饰。是的,如果我将它们实例化为类,这很好,但当我尝试使用注入器时,它会抛出错误。如果我只需要没有其他注入器的简单服务,我喜欢你的想法,我认为标准类可以很好地工作,但是如果我尝试向我想要扩展的类中注入一些东西(比如UserService),它会再次抛出错误。很好看@CH Buckingham,我搞砸了你的发现,它确实允许我传递其他信息,但它不允许我简单地“扩展”服务。做这件事需要大量的代码,这有点挫败了扩展的想法。我正在发布一个我发现的答案。。这并不完美,但很有效。嗨,丹尼斯·斯莫莱克,我能问你两个问题吗。1.如果组件类(命名子类)从父类扩展而来,如何将参数传递给子类中的构造函数?2.子组件如何从父组件扩展并传递参数?对于服务:因为注入器处理所有服务的初始化,所以在运行时无法在构造函数中动态传递任何内容,但可以灵活地编写服务代码。例如,我的主服务拥有运行我的Firebase函数的所有代码,然后子服务设置自己的Firebase URL并继承所有父函数。我的子服务覆盖父服务的“init”函数。在我的代码中,这将是“myString”参数。对于组件:它取决于您何时扩展它。如果你想制作一个按钮组件,然后为了一些特殊的功能而扩展它,这很简单,就像我扩展服务的方式一样。如果您想在运行时执行此操作(可能是更简单的想法),您可以在调用组件时设置一些input()值。如果你指的是父/子嵌套组件,那么有很多方法可以传递数据、eventEmitter、父对象,甚至是服务..Dennis你在plunker打印一个异常。mautrok,这个答案非常古老(不管怎么说,对于ng2),所以我肯定有些东西被移动/破坏了。我将看一下rc.5,看看这是否仍然适用,并尝试在某个时候更新plunker。什么是
DEFAULT\u CONFIG
?感谢您的关注。我修好了儿童服务。默认的_配置用于指示数据和管道的源,可以是简单URL或带有事件名称的websocket URL。
@Injectable()
export class GenericStore {
   ....
   constructor(public config:GenericConfig,private http:Http) {
        ....
   }
   ....
}
const DEFAULT_CONFIG:GenericConfig = { ... };
@Injectable()
export class ConfigStore extends GenericStore {
   ....
   constructor(private anotherHttp:Http) {
        super(DEFAULT_CONFIG,anotherHttp);
   }
   ....
}
abstract class GenericStore{

  abstract configVal: string;

  constructor(){}

  someMethod(){
    console.log('The config value is:', this.configVal);
  }
}

class UserStore extends GenericStore{

  configVal = 'A config value. Typescript will yell if not provided.'; 

  constructor(){
    super();
  }
}