Aurelia工厂旋转变压器使用参数装饰(非类装饰)

时间:2018-03-01 02:07:45

标签: typescript aurelia

我知道如何使用@inject类装饰器使用aurelia工厂解析器:

@inject(Factory.of(Foo))
export class NeedsFoo {
  foo: Foo;
  constructor(fooFactory: () => Foo) {
    this.foo = fooFactory(config);
  }
}

config是初始化Foo实例所需的一些配置状态,无法注入。

但是在一些较大的视图模型中,@autoinject更好更容易添加/删除依赖项,但我无法弄清楚如何使用参数装饰器来实现相同的功能。

解析器简要记录here,没有工厂解析器属性的示例。一个相关的错误是here,但我无法从中找出用法。有一堆SO问题,但它们都引用@inject(Factory.of(...))

如果我尝试以下操作,那么fooFactory就是一个空对象{}

@autoinject()
export class NeedsFoo {
  foo: Foo;
  constructor(@factory(Foo) fooFactory) {
    this.foo = fooFactory(config);
  }
}

对bug讨论的评论说:

interface FooFactory {
  new (config: any): Foo;
}

class NeedsFoo {
  foo: Foo;
  constructor(@factory(Foo) fooFactory: FooFactory) {
    this.foo = new fooFactory(config); // error!
  }
}

但标记的行以TypeError: fooFactory is not a constructor.(它是一个空对象)

失败

我可以使用参数装饰器和自动注入来为Aurelia注入类的工厂吗?

编辑:将 deps 重命名为 config ,因此看起来我没有传递注入的依赖项。

编辑2:fooFactory是一个空对象,不是未定义的

1 个答案:

答案 0 :(得分:3)

你非常接近。只需在第二个示例中将@autoinject()添加到NeedsFoo,摆脱deps参数,如果它有自己的deps,也不要忘记将@autoinject()放在Foo上。

进一步阐明其工作方式/原因,并消除一些误解:

  • 在类上放置任何装饰器将使tsc为该类发出类型元数据。如果类中没有其他装饰器,则只能使用autoinject。已经是@customElement()了吗?无需@autoinject()

  • 从不需要将依赖项传递给工厂函数。它们由工厂功能内的容器检索。

  • 工厂函数不是类构造函数,它是构造函数。将其作为fooFactory()new fooFactory()调用具有相同的效果:它调用函数并返回函数返回的任何内容。

  • 接口不能编译为javascript。使用接口作为参数类型永远不会使DI工作。 : FooFactory这里跟: any一样。这仅适用于intellisense。

  • 使用@factory()时,传递给函数的类型将取代参数本身的类型。参数的类型将被忽略。

这为您提供了几种替代实现。

给出以下类Foo

@autoinject()
export class Foo {
    public bar: Bar;
    constructor(bar: Bar) {
        this.bar = bar;
    }
}

任何这些类NeedsFoo:

@autoinject()
export class NeedsFoo {
    public foo: Foo;
    constructor(@factory(Foo) fooFactory: any) {
        this.foo = new fooFactory();
    }
}

@customElement("needs-foo")
export class NeedsFoo {
    public foo: Foo;
    constructor(@factory(Foo) fooFactory: FooFactory) {
        this.foo = new fooFactory();
    }
}

@autoinject()
export class NeedsFoo {
    public foo: Foo;
    constructor(@factory(Foo) fooFactory: any) {
        this.foo = fooFactory();
    }
}

@autoinject()
export class NeedsFoo {
    public foo: Foo;
    constructor(@factory(Foo) fooFactory: FooFactory ) {
        this.foo = new fooFactory();
    }
}
interface FooFactory {
    new(): Foo;
}

他们(以及他们的不同组合)都是相同的,并为您提供了Foo的实例。