Skip to content

Commit 62b1e19

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 e00cefa commit 62b1e19

File tree

2 files changed

+43
-10
lines changed

2 files changed

+43
-10
lines changed

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

Lines changed: 24 additions & 0 deletions
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

Lines changed: 19 additions & 10 deletions
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,8 @@ 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+
dependency.instances.push(resolver);
286287
}
287288

288289
this.modules[name] = dependency;
@@ -370,26 +371,32 @@ export class Yok implements IInjector {
370371
pushIndent();
371372

372373
let dependency: IDependency;
374+
let instance: any;
373375
try {
374376
dependency = this.resolveDependency(name);
375377

376378
if (!dependency) {
377379
throw new Error("unable to resolve " + name);
378380
}
379381

380-
if (!dependency.instance || !dependency.shared) {
382+
if (!dependency.instances || !dependency.instances.length || !dependency.shared) {
381383
if (!dependency.resolver) {
382384
throw new Error("no resolver registered for " + name);
383385
}
384386

385-
dependency.instance = this.resolveConstructor(dependency.resolver, ctorArguments);
387+
dependency.instances = dependency.instances || [];
388+
389+
instance = this.resolveConstructor(dependency.resolver, ctorArguments);
390+
dependency.instances.push(instance);
391+
} else {
392+
instance = _.first(dependency.instances);
386393
}
387394
} finally {
388395
popIndent();
389396
delete this.resolutionProgress[name];
390397
}
391398

392-
return dependency.instance;
399+
return instance;
393400
}
394401

395402
private resolveDependency(name: string): IDependency {
@@ -424,10 +431,12 @@ export class Yok implements IInjector {
424431

425432
public dispose(): void {
426433
Object.keys(this.modules).forEach((moduleName) => {
427-
const instance = this.modules[moduleName].instance;
428-
if (instance && instance.dispose && instance !== this) {
429-
instance.dispose();
430-
}
434+
const instances = this.modules[moduleName].instances;
435+
_.forEach(instances, instance => {
436+
if (instance && instance.dispose && instance !== this) {
437+
instance.dispose();
438+
}
439+
});
431440
});
432441
}
433442
}

0 commit comments

Comments
 (0)