【问题标题】:Factory with parameters in InversifyJSInversifyJS 中带参数的工厂
【发布时间】:2017-04-07 15:43:51
【问题描述】:

我将InversifyJS 与 TypeScript 一起使用。

假设我有一个混合了注入和非注入构造函数参数的类:

@injectable()
export class MyClass {
    constructor(
      foo: Foo, // This thing isn't injectable
      @inject(Bar) bar: Bar // This thing is
   ){
      ...
   }
}

我想将这个类的工厂注入到其他类中,然后用第一个参数的值调用它。

@injectable()
export class SomeOtherClass {
   constructor(
      @inject("Factory<MyClass>") myClassFactory: (foo: Foo) => MyClass
   ){
      const someFoo = new Foo();
      const myClass = myClassFactory(someFoo);
   }
}

我的问题:Inversify 中是否有一些自动魔法可以让我注入这个工厂?

到目前为止,我想出的最好的是:

bind<interfaces.Factory<MyClass>>("Factory<MyClass>").toFactory(context =>
    (foo: Foo) => 
        new MyClass(foo, context.kernel.get<Bar>(Bar))
);

但这意味着我明确地new()-ing MyClass 并且MyClass 的每个新的可注入依赖项也必须在这里添加。

有没有更好的方法?也许是基于参数名称的东西,比如Ninject Factory Extensions

【问题讨论】:

    标签: typescript dependency-injection inversifyjs


    【解决方案1】:

    我是 InversifyJS 的作者。我认为在工厂内部使用new 没有问题,记住工厂的工作是创建一个new实例。

    在工厂内多次调用container.get&lt;T&gt;确实是not a good thing

    我可以建议将MyClass 的初始化分成几个阶段:

    工厂实例化的类:

    @injectable()
    export class MyClass {
    
        public c: C; // This thing isn't injectable
        public d: D; // This thing isn't injectable
    
        // PHASE 1: instantiation
        constructor(
          @inject(A) a: A // This thing is
          @inject(B) b: B // This thing is
       ){
          ...
       }
    
       // PHASE 2: initialization
       public init(c: C, d: D) {
          this.c = c;
          this.d = d;
       }
    
    }
    

    使用工厂的类:

    @injectable()
    export class SomeOtherClass {
       constructor(
          @inject("Factory<MyClass>") myClassFactory: (c: C, d: D) => MyClass
       ){
          // you only use "new" with entities that are not injected by inversify
          const c = new C(); 
          const d = new D();
          const myClass = myClassFactory(c, d);
       }
    }
    

    还有工厂:

    bind<interfaces.Factory<MyClass>>("Factory<MyClass>").toFactory(context =>
        (c: C, d, D) => {
    
            // PHASE 1: instantiation
            let myClass = context.kernel.get<MyClass>("MyClass"); // a and b are injected
    
            // PHASE 2: initialization
            myClass.init(c, d); // c and d are initialized
    
            return myClass;
    
        }
    );
    

    希望对您有所帮助,如果您认为自己知道更好的方法,请分享您对 GitHub 问题的想法。

    【讨论】:

    • 谢谢。这绝对是对必须 get() 类的每个依赖项的改进。也就是说,我可能会在 GitHub 上建议另一种方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 2020-12-27
    • 1970-01-01
    相关资源
    最近更新 更多