Skip to content

Commit 478e56b

Browse files
fix: handle correctly non-shared instances in injector
Currently `$injector` can have non-shared instances by setting the third argument of the `register` method to false, i.e.: ``` $injector.register("myClass", MyClass, false); ``` However, in this case, the injector caches only the last created instance and this way it will not call the dispose method of all created instances. Fix this by caching all instances in an array and iterrate over them when disposing them. This way we can have correct resolving of instances by name when constructor has non-injectable dependencies: ``` class A { constructor(private stringArg: string) { } } $injector.register("a", A, false); // in another file: $injector.resolve("a", { stringArg: "stringValue" }); //returns new instance; $injector.resolve("a", { stringArg: "different stringValue" }); //returns new instance; ```
1 parent 545b3a5 commit 478e56b

File tree

2 files changed

+47
-10
lines changed

2 files changed

+47
-10
lines changed

lib/common/test/unit-tests/yok.ts

+24
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,30 @@ describe("yok", () => {
227227
assert.isTrue(thing.disposed);
228228
});
229229

230+
it("disposes all instances", () => {
231+
const injector = new Yok();
232+
233+
function Thing(arg: string) { this.arg = arg; /* intentionally left blank */ }
234+
235+
Thing.prototype.dispose = function () {
236+
this.disposed = true;
237+
};
238+
239+
injector.register("thing", Thing, false);
240+
const thing1 = injector.resolve("thing", { arg: "thing1"});
241+
const thing2 = injector.resolve("thing", { arg: "thing2"});
242+
const thing3 = injector.resolve("thing", { arg: "thing3"});
243+
244+
assert.equal(thing1.arg, "thing1");
245+
assert.equal(thing2.arg, "thing2");
246+
assert.equal(thing3.arg, "thing3");
247+
injector.dispose();
248+
249+
assert.isTrue(thing1.disposed);
250+
assert.isTrue(thing2.disposed);
251+
assert.isTrue(thing3.disposed);
252+
});
253+
230254
});
231255

232256
describe("classes", () => {

lib/common/yok.ts

+23-10
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export function register(...rest: any[]) {
4040
export interface IDependency {
4141
require?: string;
4242
resolver?: () => any;
43-
instance?: any;
43+
instances?: any[];
4444
shared?: boolean;
4545
}
4646

@@ -128,7 +128,7 @@ export class Yok implements IInjector {
128128
}
129129

130130
private resolveInstance(name: string): any {
131-
let classInstance = this.modules[name].instance;
131+
let classInstance = _.first(this.modules[name].instances);
132132
if (!classInstance) {
133133
classInstance = this.resolve(name);
134134
}
@@ -282,7 +282,12 @@ export class Yok implements IInjector {
282282
if (_.isFunction(resolver)) {
283283
dependency.resolver = resolver;
284284
} else {
285-
dependency.instance = resolver;
285+
dependency.instances = dependency.instances || [];
286+
if (shared) {
287+
dependency.instances[0] = resolver;
288+
} else {
289+
dependency.instances.push(resolver);
290+
}
286291
}
287292

288293
this.modules[name] = dependency;
@@ -370,26 +375,32 @@ export class Yok implements IInjector {
370375
pushIndent();
371376

372377
let dependency: IDependency;
378+
let instance: any;
373379
try {
374380
dependency = this.resolveDependency(name);
375381

376382
if (!dependency) {
377383
throw new Error("unable to resolve " + name);
378384
}
379385

380-
if (!dependency.instance || !dependency.shared) {
386+
if (!dependency.instances || !dependency.instances.length || !dependency.shared) {
381387
if (!dependency.resolver) {
382388
throw new Error("no resolver registered for " + name);
383389
}
384390

385-
dependency.instance = this.resolveConstructor(dependency.resolver, ctorArguments);
391+
dependency.instances = dependency.instances || [];
392+
393+
instance = this.resolveConstructor(dependency.resolver, ctorArguments);
394+
dependency.instances.push(instance);
395+
} else {
396+
instance = _.first(dependency.instances);
386397
}
387398
} finally {
388399
popIndent();
389400
delete this.resolutionProgress[name];
390401
}
391402

392-
return dependency.instance;
403+
return instance;
393404
}
394405

395406
private resolveDependency(name: string): IDependency {
@@ -424,10 +435,12 @@ export class Yok implements IInjector {
424435

425436
public dispose(): void {
426437
Object.keys(this.modules).forEach((moduleName) => {
427-
const instance = this.modules[moduleName].instance;
428-
if (instance && instance.dispose && instance !== this) {
429-
instance.dispose();
430-
}
438+
const instances = this.modules[moduleName].instances;
439+
_.forEach(instances, instance => {
440+
if (instance && instance.dispose && instance !== this) {
441+
instance.dispose();
442+
}
443+
});
431444
});
432445
}
433446
}

0 commit comments

Comments
 (0)