Closed serebro closed 7 years ago
Hi,
Thanks for your feedback. I did not test it with target ES6 yet. But I will fix this as soon as possible.
It is fixed on 0.2.8 version
Very cool! Thanks.
Sorry, but I found another problem related.
with ES5, I can do this, when creating an object inside the container:
IoCContainer.applyInjections(this, target);
target.apply(this, args);
Note that I apply all class injections before run the class constructor (the target on the given code).
This is nice because it allow me to write things like:
@AutoWired
class Test {
@Inject private test2: Test2
constructor() {
console.log(this.test2);
}
}
I can access the injected property test2 inside the constructor.
The problem is: ES6 classes does not allow this kind of instantiation. The 'this' property does not exists before the new command is called (and the object created)
So, if I want to make it work for ES6 classes, I have to change the above example to:
@AutoWired
class Test {
private test2: Test2
constructor(@Inject test2: Test2) {
this.test2 = test2;
console.log(this.test2);
}
}
I am really trying to find a solution for this. This commit solves the ES6 problem but it breaks the compatibility, once the injected properties stop to work on constructors.
Any suggestions?
If the only solution is to apply the injections after the object creation, we will have to create a new major version that breaks the compatibility (or keep using ES5 :( )
I found a new solution.
I dont't apply the injections inside a modified constructor anymore.
I changed the @Inject
annotation to modify the class prototype to handle these injections as a class property. So, now I have a get and set functions to handle injected properties. It solves the es6 problem (as I don't need to change the constructor anymore) and has a very nice side effect: It increase the performance, once now the container only have to inject a property if it is already used.
This is the method that handle the @Inject
decorator on a class property:
static injectProperty(target: Function, key: string, propertyType: Function) {
const propKey = `__${key}`;
Object.defineProperty(target.prototype, key, {
enumerable: true,
get: function(){
return this[propKey]?this[propKey]:this[propKey]=IoCContainer.get(propertyType);
},
set: (newValue) => {
this[propKey] = newValue;
}
});
}
So, if you write:
@AutoWired
class SimpleInject {
@Inject
aDateProperty: Date;
constructor() {
if (this.aDateProperty)
console.log('It works');
}
}
The IoC Container will only inject the property aDateProperty
when it is first accessed (in this example, when the constructor executes).
Hi Thiago,
When i tried to run this code with target
es6
of compilerOptions I got the errorTypeError: Class constructor SimppleInject cannot be invoked without 'new'
I use typescript 2.1.5.
tsconfig.json
Thanks for your IoC!