问题
I'm using InversifyJS with TypeScript.
Let's say I have a class which has a mixture of injected and non-injected constructor parameters:
@injectable()
export class MyClass {
constructor(
foo: Foo, // This thing isn't injectable
@inject(Bar) bar: Bar // This thing is
){
...
}
}
I would like to inject a factory for this class into some other class and then invoke it with a value for the first parameter.
@injectable()
export class SomeOtherClass {
constructor(
@inject("Factory<MyClass>") myClassFactory: (foo: Foo) => MyClass
){
const someFoo = new Foo();
const myClass = myClassFactory(someFoo);
}
}
My question: is there some auto-magic in Inversify that will allow me to inject this factory?
The best I've come up with so far is this:
bind<interfaces.Factory<MyClass>>("Factory<MyClass>").toFactory(context =>
(foo: Foo) =>
new MyClass(foo, context.kernel.get<Bar>(Bar))
);
But that means I'm explicitly new()
-ing MyClass
and every new injectable dependency of MyClass
has to be added here too.
Is there a better way? Perhaps something based on parameter names like Ninject Factory Extensions?
回答1:
I'm the author of InversifyJS. I don't think there is a problem about using new
inside the factory, remember that the job of the factory is to create a new instance.
It is true that calling container.get<T>
multiple times inside a factory is not a good thing.
I can suggest breaking the initialization of MyClass
into to phases:
The class instantiated by the factory:
@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;
}
}
The class that uses the factory:
@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);
}
}
And the factory:
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;
}
);
I hope it helps and please share your ideas on the GitHub issues if you think you know a better way.
来源:https://stackoverflow.com/questions/40767730/factory-with-parameters-in-inversifyjs