typescript - 使用参数修饰(不是类修饰)的 Aurelia 工厂解析器

标签 typescript aurelia

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

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

config 是初始化 Foo 实例所需的一些配置状态,不能注入(inject)。

但在一些更大的 View 模型中,@autoinject 更好更容易添加/删除依赖项,但我不知道如何使用参数装饰器来实现同样的事情。

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

如果我尝试以下操作,则 fooFactory 是一个空对象 {}:

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

错误讨论的评论说要这样做:

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.(它是一个空对象)

我可以使用参数装饰器和自动注入(inject)来使用 Aurelia 注入(inject)一个类的工厂吗?


编辑:将 deps 重命名为 config 这样我就不会传递注入(inject)的依赖项了。

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

最佳答案

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

进一步阐明这是如何/为什么起作用并消除一些误解:

  • 在类上放置任何 装饰器将使 tsc 发出该类的类型元数据。如果类中没有其他装饰器,您只会使用自动注入(inject)。是不是已经有@customElement()了?不需要 @autoinject()

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

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

  • 接口(interface)不会编译为 javascript。使用接口(interface)作为参数类型永远不会使 DI 工作。 : FooFactory 这里和说: any 是一样的。这仅用于智能感知。

  • 使用 @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 实例。

关于typescript - 使用参数修饰(不是类修饰)的 Aurelia 工厂解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49041550/

相关文章:

css - aurelia-cli 元素 : height in %, 和 bundle 导出的 Kendo UI 拆分器?

typescript - 如何连接扩展/继承相同类型的两个不同数组类型?

javascript - 为什么我无法访问主题上的管道方法?

javascript - 在javascript数组中按值获取索引

angular - 如何解决在 Angular 6 中为业力测试抛出的 [object ErrorEvent]

javascript - Aurelia - 在下拉列表中设置默认值

electron - 需要帮助在 Aurelia 应用程序中导入 Electron

windows - Aurelia:如何获取用户窗口的用户名

typescript - "Cannot find name ' ServiceWorkerRegistration 使用Typescript创建firebase云函数时出现'"错误

javascript - 从另一个自定义属性访问自定义属性的绑定(bind)