【问题标题】:How can I get new instances of a class using Injector instead of singleton如何使用 Injector 而不是单例获取类的新实例
【发布时间】:2018-02-07 15:35:06
【问题描述】:

我的 Angular 应用程序中有两个可注入类

@Injectable()
class B {}

@Injectable()
class A {
  constructor(b:B) { }
}

我希望 A 类是单例,B 类是瞬态

我知道我可以在 A 类中使用 ReflectiveInjector.resolveAndCreate 来获取 B 类的实例。有更好的方法来实现这一点吗?

【问题讨论】:

标签: angular dependency-injection


【解决方案1】:

由于提供者的所有现有配方都创建单例,甚至工厂,您可以创建自己的注入器,从组件注入器继承所有提供者并使用resolveAndInstantiate 方法每次获取新实例:

import { Component, Inject, Injector, ReflectiveInjector } from '@angular/core';

class P {
}

const ps = [];

class C {
  constructor(@Inject(P) p) {
    ps.push(p);
  }
}

@Component({
  moduleId: module.id,
  selector: 'my-app',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css']
})
export class AppComponent {
  name = 'Angular';

  constructor(injector: Injector) {
    const parent = ReflectiveInjector.resolveAndCreate([P], injector);
    const child = parent.resolveAndCreateChild([C]);
    const c1 = child.resolveAndInstantiate(C);
    const c2 = child.resolveAndInstantiate(C);
    console.log(c1 === c2); // false

    console.log(ps[0] === ps[1]); // true

  }
}

Here is the demo.

还请记住,ReflectiveInjector 在 @5.x.x 中已弃用。似乎在新的StaticInjector 中没有其他选择。我报告了an issue。

【讨论】:

  • 感谢马克西姆的回答。不过我有一个问题,我们不能使用常规工厂方法在需要时返回所需对象的新实例吗?其次,ReflectiveInjector 不被弃用吗?你还推荐使用吗
  • @SRK,不,工厂不会每次都返回新实例,无论它第一次缓存它时返回什么。所以即使你在里面做return new AClass(),你仍然会得到一个单例
  • @SRK 另外,请记住 ReflectiveInjector 已被弃用。而且似乎在新的 StaticInjector 中没有其他选择。我reported an issue 关于那个。你可以阅读更多关于 StaticInjector here
  • 谢谢。直到现在我的印象是每次调用工厂都会返回一个新实例。
【解决方案2】:

有一种方法可以使用 StaticInjector 和函数式 Javascript 来解决这个问题。使用 Max Koretskyi 的答案,我想出了一些修改:

import { Component, Inject, Injector } from '@angular/core';

class P {
}

const ps = [];

function pFactory() {
  return () => new P();
}

@Component({
  moduleId: module.id,
  providers: [{provide: pFactory, deps: [], useFactory: (pFactory)}],
  selector: 'my-app',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css']
})
export class AppComponent {
  name = 'Angular';

  constructor(@Inject(pFactory) pf) {
    let fn = pf.get(pFactory)
    ps.push(fn());
    ps.push(fn());
    console.log(ps[0] === ps[1]); // false
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-17
    • 2012-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-31
    相关资源
    最近更新 更多