From b60c10392588b49b6b3ea2fb20c75c27c2a73bb5 Mon Sep 17 00:00:00 2001 From: Rob Eisenberg Date: Thu, 15 Oct 2015 16:30:48 -0400 Subject: [PATCH] fix(registrations): properly handle registrations that want to target different containers --- config.js | 120 +++-- dist/amd/aurelia-dependency-injection.d.ts | 164 +++--- dist/amd/aurelia-dependency-injection.js | 5 +- dist/aurelia-dependency-injection.d.ts | 164 +++--- dist/aurelia-dependency-injection.js | 483 +++++++++--------- .../aurelia-dependency-injection.d.ts | 164 +++--- dist/commonjs/aurelia-dependency-injection.js | 5 +- dist/es6/aurelia-dependency-injection.d.ts | 164 +++--- dist/es6/aurelia-dependency-injection.js | 483 +++++++++--------- dist/system/aurelia-dependency-injection.d.ts | 164 +++--- dist/system/aurelia-dependency-injection.js | 5 +- src/container.js | 3 +- src/registrations.js | 2 +- 13 files changed, 965 insertions(+), 961 deletions(-) diff --git a/config.js b/config.js index 562564c..0cbd9fd 100644 --- a/config.js +++ b/config.js @@ -1,61 +1,59 @@ -System.config({ - defaultJSExtensions: true, - transpiler: "babel", - babelOptions: { - "optional": [ - "runtime", - "es7.decorators", - "es7.classProperties" - ] - }, - paths: { - "github:*": "jspm_packages/github/*", - "aurelia-dependency-injection/*": "dist/*", - "npm:*": "jspm_packages/npm/*" - }, - - map: { - "aurelia-logging": "github:aurelia/logging@0.8.0", - "aurelia-metadata": "github:aurelia/metadata@0.9.0", - "aurelia-pal": "github:aurelia/pal@0.2.0", - "babel": "npm:babel-core@5.1.13", - "babel-runtime": "npm:babel-runtime@5.1.13", - "core-js": "npm:core-js@1.2.1", - "github:aurelia/metadata@0.9.0": { - "aurelia-pal": "github:aurelia/pal@0.2.0", - "core-js": "npm:core-js@0.9.18" - }, - "github:jspm/nodelibs-assert@0.1.0": { - "assert": "npm:assert@1.3.0" - }, - "github:jspm/nodelibs-process@0.1.2": { - "process": "npm:process@0.11.2" - }, - "github:jspm/nodelibs-util@0.1.0": { - "util": "npm:util@0.10.3" - }, - "npm:assert@1.3.0": { - "util": "npm:util@0.10.3" - }, - "npm:core-js@0.9.18": { - "fs": "github:jspm/nodelibs-fs@0.1.2", - "process": "github:jspm/nodelibs-process@0.1.2", - "systemjs-json": "github:systemjs/plugin-json@0.1.0" - }, - "npm:core-js@1.2.1": { - "fs": "github:jspm/nodelibs-fs@0.1.2", - "process": "github:jspm/nodelibs-process@0.1.2", - "systemjs-json": "github:systemjs/plugin-json@0.1.0" - }, - "npm:inherits@2.0.1": { - "util": "github:jspm/nodelibs-util@0.1.0" - }, - "npm:process@0.11.2": { - "assert": "github:jspm/nodelibs-assert@0.1.0" - }, - "npm:util@0.10.3": { - "inherits": "npm:inherits@2.0.1", - "process": "github:jspm/nodelibs-process@0.1.2" - } - } -}); +System.config({ + defaultJSExtensions: true, + transpiler: "babel", + babelOptions: { + "optional": [ + "runtime", + "es7.decorators", + "es7.classProperties" + ] + }, + paths: { + "github:*": "jspm_packages/github/*", + "aurelia-dependency-injection/*": "dist/*", + "npm:*": "jspm_packages/npm/*" + }, + + map: { + "aurelia-logging": "github:aurelia/logging@0.8.0", + "aurelia-metadata": "github:aurelia/metadata@0.9.0", + "aurelia-pal": "github:aurelia/pal@0.2.0", + "babel": "npm:babel-core@5.8.25", + "babel-runtime": "npm:babel-runtime@5.8.25", + "core-js": "npm:core-js@0.9.18", + "github:aurelia/metadata@0.9.0": { + "aurelia-pal": "github:aurelia/pal@0.2.0", + "core-js": "npm:core-js@0.9.18" + }, + "github:jspm/nodelibs-assert@0.1.0": { + "assert": "npm:assert@1.3.0" + }, + "github:jspm/nodelibs-process@0.1.2": { + "process": "npm:process@0.11.2" + }, + "github:jspm/nodelibs-util@0.1.0": { + "util": "npm:util@0.10.3" + }, + "npm:assert@1.3.0": { + "util": "npm:util@0.10.3" + }, + "npm:babel-runtime@5.8.25": { + "process": "github:jspm/nodelibs-process@0.1.2" + }, + "npm:core-js@0.9.18": { + "fs": "github:jspm/nodelibs-fs@0.1.2", + "process": "github:jspm/nodelibs-process@0.1.2", + "systemjs-json": "github:systemjs/plugin-json@0.1.0" + }, + "npm:inherits@2.0.1": { + "util": "github:jspm/nodelibs-util@0.1.0" + }, + "npm:process@0.11.2": { + "assert": "github:jspm/nodelibs-assert@0.1.0" + }, + "npm:util@0.10.3": { + "inherits": "npm:inherits@2.0.1", + "process": "github:jspm/nodelibs-process@0.1.2" + } + } +}); diff --git a/dist/amd/aurelia-dependency-injection.d.ts b/dist/amd/aurelia-dependency-injection.d.ts index e801469..0187213 100644 --- a/dist/amd/aurelia-dependency-injection.d.ts +++ b/dist/amd/aurelia-dependency-injection.d.ts @@ -3,121 +3,121 @@ declare module 'aurelia-dependency-injection' { import { metadata, decorators } from 'aurelia-metadata'; import { AggregateError } from 'aurelia-pal'; - /** - * An abstract resolver used to allow functions/classes to specify custom dependency resolution logic. + /** + * An abstract resolver used to allow functions/classes to specify custom dependency resolution logic. */ export class Resolver { - /** - * Called by the container to allow custom resolution of dependencies for a function/class. - * @param container The container to resolve from. - * @return Returns the resolved object. + /** + * Called by the container to allow custom resolution of dependencies for a function/class. + * @param container The container to resolve from. + * @return Returns the resolved object. */ get(container: Container): any; } - /** - * Used to allow functions/classes to specify lazy resolution logic. + /** + * Used to allow functions/classes to specify lazy resolution logic. */ export class Lazy extends Resolver { - /** - * Creates an instance of the Lazy class. - * @param key The key to lazily resolve. + /** + * Creates an instance of the Lazy class. + * @param key The key to lazily resolve. */ constructor(key: any); - /** - * Called by the container to lazily resolve the dependency into a lazy locator function. - * @param container The container to resolve from. - * @return Returns a function which can be invoked at a later time to obtain the actual dependency. + /** + * Called by the container to lazily resolve the dependency into a lazy locator function. + * @param container The container to resolve from. + * @return Returns a function which can be invoked at a later time to obtain the actual dependency. */ get(container: Container): any; - /** - * Creates a Lazy Resolver for the supplied key. - * @param key The key to lazily resolve. - * @return Returns an insance of Lazy for the key. + /** + * Creates a Lazy Resolver for the supplied key. + * @param key The key to lazily resolve. + * @return Returns an insance of Lazy for the key. */ static of(key: any): Lazy; } - /** - * Used to allow functions/classes to specify resolution of all matches to a key. + /** + * Used to allow functions/classes to specify resolution of all matches to a key. */ export class All extends Resolver { - /** - * Creates an instance of the All class. - * @param key The key to lazily resolve all matches for. + /** + * Creates an instance of the All class. + * @param key The key to lazily resolve all matches for. */ constructor(key: any); - /** - * Called by the container to resolve all matching dependencies as an array of instances. - * @param container The container to resolve from. - * @return Returns an array of all matching instances. + /** + * Called by the container to resolve all matching dependencies as an array of instances. + * @param container The container to resolve from. + * @return Returns an array of all matching instances. */ get(container: Container): any[]; - /** - * Creates an All Resolver for the supplied key. - * @param key The key to resolve all instances for. - * @return Returns an insance of All for the key. + /** + * Creates an All Resolver for the supplied key. + * @param key The key to resolve all instances for. + * @return Returns an insance of All for the key. */ static of(key: any): All; } - /** - * Used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. + /** + * Used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. */ export class Optional extends Resolver { - /** - * Creates an instance of the Optional class. - * @param key The key to optionally resolve for. - * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + /** + * Creates an instance of the Optional class. + * @param key The key to optionally resolve for. + * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. */ constructor(key: any, checkParent?: boolean); - /** - * Called by the container to provide optional resolution of the key. - * @param container The container to resolve from. - * @return Returns the instance if found; otherwise null. + /** + * Called by the container to provide optional resolution of the key. + * @param container The container to resolve from. + * @return Returns the instance if found; otherwise null. */ get(container: Container): any; - /** - * Creates an Optional Resolver for the supplied key. - * @param key The key to optionally resolve for. - * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. - * @return Returns an insance of Optional for the key. + /** + * Creates an Optional Resolver for the supplied key. + * @param key The key to optionally resolve for. + * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + * @return Returns an insance of Optional for the key. */ static of(key: any, checkParent?: boolean): Optional; } - /** - * Used to inject the dependency from the parent container instead of the current one. + /** + * Used to inject the dependency from the parent container instead of the current one. */ export class Parent extends Resolver { - /** - * Creates an instance of the Parent class. - * @param key The key to resolve from the parent container. + /** + * Creates an instance of the Parent class. + * @param key The key to resolve from the parent container. */ constructor(key: any); - /** - * Called by the container to load the dependency from the parent container - * @param container The container to resolve the parent from. - * @return Returns the matching instance from the parent container + /** + * Called by the container to load the dependency from the parent container + * @param container The container to resolve the parent from. + * @return Returns the matching instance from the parent container */ get(container: Container): any; - /** - * Creates a Parent Resolver for the supplied key. - * @param key The key to resolve. - * @return Returns an insance of Parent for the key. + /** + * Creates a Parent Resolver for the supplied key. + * @param key The key to resolve. + * @return Returns an insance of Parent for the key. */ static of(key: any): Parent; } @@ -154,44 +154,44 @@ declare module 'aurelia-dependency-injection' { invokeWithDynamicDependencies(container: any, fn: any, keys: any, deps: any): any; } - /** - * Used to allow functions/classes to indicate that they should be registered as transients with the container. + /** + * Used to allow functions/classes to indicate that they should be registered as transients with the container. */ export class TransientRegistration { - /** - * Creates an instance of TransientRegistration. - * @param key The key to register as. + /** + * Creates an instance of TransientRegistration. + * @param key The key to register as. */ constructor(key: any); - /** - * Called by the container to register the annotated function/class as transient. - * @param container The container to register with. - * @param key The key to register as. - * @param fn The function to register (target of the annotation). - * @return The resolver that should to be used. + /** + * Called by the container to register the annotated function/class as transient. + * @param container The container to register with. + * @param key The key to register as. + * @param fn The function to register (target of the annotation). + * @return The resolver that should to be used. */ createResolver(container: Container, key: any, fn: Function): Resolver; } - /** - * Used to allow functions/classes to indicate that they should be registered as singletons with the container. + /** + * Used to allow functions/classes to indicate that they should be registered as singletons with the container. */ export class SingletonRegistration { - /** - * Creates an instance of SingletonRegistration. - * @param key The key to register as. + /** + * Creates an instance of SingletonRegistration. + * @param key The key to register as. */ constructor(keyOrRegisterInChild: any, registerInChild?: boolean); - /** - * Called by the container to register the annotated function/class as a singleton. - * @param container The container to register with. - * @param key The key to register as. - * @param fn The function to register (target of the annotation). - * @return The resolver that should to be used. + /** + * Called by the container to register the annotated function/class as a singleton. + * @param container The container to register with. + * @param key The key to register as. + * @param fn The function to register (target of the annotation). + * @return The resolver that should to be used. */ createResolver(container: Container, key: any, fn: Function): Resolver; } diff --git a/dist/amd/aurelia-dependency-injection.js b/dist/amd/aurelia-dependency-injection.js index 4fdba39..430711d 100644 --- a/dist/amd/aurelia-dependency-injection.js +++ b/dist/amd/aurelia-dependency-injection.js @@ -249,7 +249,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-pal'], function (expo var resolver = new StrategyResolver(1, fn); if (!this.registerInChild && container !== container.root) { - container.root.registerResolver(this.key || key, resolver); + this.targetContainer = container.root; } return resolver; @@ -390,7 +390,8 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-pal'], function (expo resolver = new StrategyResolver(0, fn); } - this.registerResolver(key === undefined ? fn : key, resolver); + var targetContainer = resolver.targetContainer || this; + targetContainer.registerResolver(key === undefined ? fn : key, resolver); return resolver; }; diff --git a/dist/aurelia-dependency-injection.d.ts b/dist/aurelia-dependency-injection.d.ts index e801469..0187213 100644 --- a/dist/aurelia-dependency-injection.d.ts +++ b/dist/aurelia-dependency-injection.d.ts @@ -3,121 +3,121 @@ declare module 'aurelia-dependency-injection' { import { metadata, decorators } from 'aurelia-metadata'; import { AggregateError } from 'aurelia-pal'; - /** - * An abstract resolver used to allow functions/classes to specify custom dependency resolution logic. + /** + * An abstract resolver used to allow functions/classes to specify custom dependency resolution logic. */ export class Resolver { - /** - * Called by the container to allow custom resolution of dependencies for a function/class. - * @param container The container to resolve from. - * @return Returns the resolved object. + /** + * Called by the container to allow custom resolution of dependencies for a function/class. + * @param container The container to resolve from. + * @return Returns the resolved object. */ get(container: Container): any; } - /** - * Used to allow functions/classes to specify lazy resolution logic. + /** + * Used to allow functions/classes to specify lazy resolution logic. */ export class Lazy extends Resolver { - /** - * Creates an instance of the Lazy class. - * @param key The key to lazily resolve. + /** + * Creates an instance of the Lazy class. + * @param key The key to lazily resolve. */ constructor(key: any); - /** - * Called by the container to lazily resolve the dependency into a lazy locator function. - * @param container The container to resolve from. - * @return Returns a function which can be invoked at a later time to obtain the actual dependency. + /** + * Called by the container to lazily resolve the dependency into a lazy locator function. + * @param container The container to resolve from. + * @return Returns a function which can be invoked at a later time to obtain the actual dependency. */ get(container: Container): any; - /** - * Creates a Lazy Resolver for the supplied key. - * @param key The key to lazily resolve. - * @return Returns an insance of Lazy for the key. + /** + * Creates a Lazy Resolver for the supplied key. + * @param key The key to lazily resolve. + * @return Returns an insance of Lazy for the key. */ static of(key: any): Lazy; } - /** - * Used to allow functions/classes to specify resolution of all matches to a key. + /** + * Used to allow functions/classes to specify resolution of all matches to a key. */ export class All extends Resolver { - /** - * Creates an instance of the All class. - * @param key The key to lazily resolve all matches for. + /** + * Creates an instance of the All class. + * @param key The key to lazily resolve all matches for. */ constructor(key: any); - /** - * Called by the container to resolve all matching dependencies as an array of instances. - * @param container The container to resolve from. - * @return Returns an array of all matching instances. + /** + * Called by the container to resolve all matching dependencies as an array of instances. + * @param container The container to resolve from. + * @return Returns an array of all matching instances. */ get(container: Container): any[]; - /** - * Creates an All Resolver for the supplied key. - * @param key The key to resolve all instances for. - * @return Returns an insance of All for the key. + /** + * Creates an All Resolver for the supplied key. + * @param key The key to resolve all instances for. + * @return Returns an insance of All for the key. */ static of(key: any): All; } - /** - * Used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. + /** + * Used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. */ export class Optional extends Resolver { - /** - * Creates an instance of the Optional class. - * @param key The key to optionally resolve for. - * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + /** + * Creates an instance of the Optional class. + * @param key The key to optionally resolve for. + * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. */ constructor(key: any, checkParent?: boolean); - /** - * Called by the container to provide optional resolution of the key. - * @param container The container to resolve from. - * @return Returns the instance if found; otherwise null. + /** + * Called by the container to provide optional resolution of the key. + * @param container The container to resolve from. + * @return Returns the instance if found; otherwise null. */ get(container: Container): any; - /** - * Creates an Optional Resolver for the supplied key. - * @param key The key to optionally resolve for. - * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. - * @return Returns an insance of Optional for the key. + /** + * Creates an Optional Resolver for the supplied key. + * @param key The key to optionally resolve for. + * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + * @return Returns an insance of Optional for the key. */ static of(key: any, checkParent?: boolean): Optional; } - /** - * Used to inject the dependency from the parent container instead of the current one. + /** + * Used to inject the dependency from the parent container instead of the current one. */ export class Parent extends Resolver { - /** - * Creates an instance of the Parent class. - * @param key The key to resolve from the parent container. + /** + * Creates an instance of the Parent class. + * @param key The key to resolve from the parent container. */ constructor(key: any); - /** - * Called by the container to load the dependency from the parent container - * @param container The container to resolve the parent from. - * @return Returns the matching instance from the parent container + /** + * Called by the container to load the dependency from the parent container + * @param container The container to resolve the parent from. + * @return Returns the matching instance from the parent container */ get(container: Container): any; - /** - * Creates a Parent Resolver for the supplied key. - * @param key The key to resolve. - * @return Returns an insance of Parent for the key. + /** + * Creates a Parent Resolver for the supplied key. + * @param key The key to resolve. + * @return Returns an insance of Parent for the key. */ static of(key: any): Parent; } @@ -154,44 +154,44 @@ declare module 'aurelia-dependency-injection' { invokeWithDynamicDependencies(container: any, fn: any, keys: any, deps: any): any; } - /** - * Used to allow functions/classes to indicate that they should be registered as transients with the container. + /** + * Used to allow functions/classes to indicate that they should be registered as transients with the container. */ export class TransientRegistration { - /** - * Creates an instance of TransientRegistration. - * @param key The key to register as. + /** + * Creates an instance of TransientRegistration. + * @param key The key to register as. */ constructor(key: any); - /** - * Called by the container to register the annotated function/class as transient. - * @param container The container to register with. - * @param key The key to register as. - * @param fn The function to register (target of the annotation). - * @return The resolver that should to be used. + /** + * Called by the container to register the annotated function/class as transient. + * @param container The container to register with. + * @param key The key to register as. + * @param fn The function to register (target of the annotation). + * @return The resolver that should to be used. */ createResolver(container: Container, key: any, fn: Function): Resolver; } - /** - * Used to allow functions/classes to indicate that they should be registered as singletons with the container. + /** + * Used to allow functions/classes to indicate that they should be registered as singletons with the container. */ export class SingletonRegistration { - /** - * Creates an instance of SingletonRegistration. - * @param key The key to register as. + /** + * Creates an instance of SingletonRegistration. + * @param key The key to register as. */ constructor(keyOrRegisterInChild: any, registerInChild?: boolean); - /** - * Called by the container to register the annotated function/class as a singleton. - * @param container The container to register with. - * @param key The key to register as. - * @param fn The function to register (target of the annotation). - * @return The resolver that should to be used. + /** + * Called by the container to register the annotated function/class as a singleton. + * @param container The container to register with. + * @param key The key to register as. + * @param fn The function to register (target of the annotation). + * @return The resolver that should to be used. */ createResolver(container: Container, key: any, fn: Function): Resolver; } diff --git a/dist/aurelia-dependency-injection.js b/dist/aurelia-dependency-injection.js index 5dab32b..02944cc 100644 --- a/dist/aurelia-dependency-injection.js +++ b/dist/aurelia-dependency-injection.js @@ -2,188 +2,188 @@ import 'core-js'; import {metadata,decorators} from 'aurelia-metadata'; import {AggregateError} from 'aurelia-pal'; -/** -* An abstract resolver used to allow functions/classes to specify custom dependency resolution logic. -*/ -export class Resolver { - /** - * Called by the container to allow custom resolution of dependencies for a function/class. - * @param container The container to resolve from. - * @return Returns the resolved object. - */ - get(container: Container): any { - throw new Error('A custom Resolver must implement get(container) and return the resolved instance(s).'); - } -} - -/** -* Used to allow functions/classes to specify lazy resolution logic. -*/ -export class Lazy extends Resolver { - /** - * Creates an instance of the Lazy class. - * @param key The key to lazily resolve. - */ - constructor(key: any) { - super(); - this.key = key; - } - - /** - * Called by the container to lazily resolve the dependency into a lazy locator function. - * @param container The container to resolve from. - * @return Returns a function which can be invoked at a later time to obtain the actual dependency. - */ - get(container: Container): any { - return () => { - return container.get(this.key); - }; - } - - /** - * Creates a Lazy Resolver for the supplied key. - * @param key The key to lazily resolve. - * @return Returns an insance of Lazy for the key. - */ - static of(key: any): Lazy { - return new Lazy(key); - } -} - -/** -* Used to allow functions/classes to specify resolution of all matches to a key. -*/ -export class All extends Resolver { - /** - * Creates an instance of the All class. - * @param key The key to lazily resolve all matches for. - */ - constructor(key: any) { - super(); - this.key = key; - } - - /** - * Called by the container to resolve all matching dependencies as an array of instances. - * @param container The container to resolve from. - * @return Returns an array of all matching instances. - */ - get(container: Container): any[] { - return container.getAll(this.key); - } - - /** - * Creates an All Resolver for the supplied key. - * @param key The key to resolve all instances for. - * @return Returns an insance of All for the key. - */ - static of(key: any): All { - return new All(key); - } -} - -/** -* Used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. -*/ -export class Optional extends Resolver { - /** - * Creates an instance of the Optional class. - * @param key The key to optionally resolve for. - * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. - */ - constructor(key: any, checkParent?: boolean = false) { - super(); - this.key = key; - this.checkParent = checkParent; - } - - /** - * Called by the container to provide optional resolution of the key. - * @param container The container to resolve from. - * @return Returns the instance if found; otherwise null. - */ - get(container: Container): any { - if (container.hasResolver(this.key, this.checkParent)) { - return container.get(this.key); - } - - return null; - } - - /** - * Creates an Optional Resolver for the supplied key. - * @param key The key to optionally resolve for. - * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. - * @return Returns an insance of Optional for the key. - */ - static of(key: any, checkParent?: boolean = false): Optional { - return new Optional(key, checkParent); - } -} - - -/** -* Used to inject the dependency from the parent container instead of the current one. -*/ -export class Parent extends Resolver { - /** - * Creates an instance of the Parent class. - * @param key The key to resolve from the parent container. - */ - constructor(key: any) { - super(); - this.key = key; - } - - /** - * Called by the container to load the dependency from the parent container - * @param container The container to resolve the parent from. - * @return Returns the matching instance from the parent container - */ - get(container: Container): any { - return container.parent - ? container.parent.get(this.key) - : null; - } - - /** - * Creates a Parent Resolver for the supplied key. - * @param key The key to resolve. - * @return Returns an insance of Parent for the key. - */ - static of(key : any) : Parent { - return new Parent(key); - } -} - -export class StrategyResolver { - constructor(strategy, state) { - this.strategy = strategy; - this.state = state; - } - - get(container, key) { - switch (this.strategy) { - case 0: //instance - return this.state; - case 1: //singleton - let singleton = container.invoke(this.state); - this.state = singleton; - this.strategy = 0; - return singleton; - case 2: //transient - return container.invoke(this.state); - case 3: //function - return this.state(container, key, this); - case 4: //array - return this.state[0].get(container, key); - case 5: //alias - return container.get(this.state); - default: - throw new Error('Invalid strategy: ' + this.strategy); - } - } -} +/** +* An abstract resolver used to allow functions/classes to specify custom dependency resolution logic. +*/ +export class Resolver { + /** + * Called by the container to allow custom resolution of dependencies for a function/class. + * @param container The container to resolve from. + * @return Returns the resolved object. + */ + get(container: Container): any { + throw new Error('A custom Resolver must implement get(container) and return the resolved instance(s).'); + } +} + +/** +* Used to allow functions/classes to specify lazy resolution logic. +*/ +export class Lazy extends Resolver { + /** + * Creates an instance of the Lazy class. + * @param key The key to lazily resolve. + */ + constructor(key: any) { + super(); + this.key = key; + } + + /** + * Called by the container to lazily resolve the dependency into a lazy locator function. + * @param container The container to resolve from. + * @return Returns a function which can be invoked at a later time to obtain the actual dependency. + */ + get(container: Container): any { + return () => { + return container.get(this.key); + }; + } + + /** + * Creates a Lazy Resolver for the supplied key. + * @param key The key to lazily resolve. + * @return Returns an insance of Lazy for the key. + */ + static of(key: any): Lazy { + return new Lazy(key); + } +} + +/** +* Used to allow functions/classes to specify resolution of all matches to a key. +*/ +export class All extends Resolver { + /** + * Creates an instance of the All class. + * @param key The key to lazily resolve all matches for. + */ + constructor(key: any) { + super(); + this.key = key; + } + + /** + * Called by the container to resolve all matching dependencies as an array of instances. + * @param container The container to resolve from. + * @return Returns an array of all matching instances. + */ + get(container: Container): any[] { + return container.getAll(this.key); + } + + /** + * Creates an All Resolver for the supplied key. + * @param key The key to resolve all instances for. + * @return Returns an insance of All for the key. + */ + static of(key: any): All { + return new All(key); + } +} + +/** +* Used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. +*/ +export class Optional extends Resolver { + /** + * Creates an instance of the Optional class. + * @param key The key to optionally resolve for. + * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + */ + constructor(key: any, checkParent?: boolean = false) { + super(); + this.key = key; + this.checkParent = checkParent; + } + + /** + * Called by the container to provide optional resolution of the key. + * @param container The container to resolve from. + * @return Returns the instance if found; otherwise null. + */ + get(container: Container): any { + if (container.hasResolver(this.key, this.checkParent)) { + return container.get(this.key); + } + + return null; + } + + /** + * Creates an Optional Resolver for the supplied key. + * @param key The key to optionally resolve for. + * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + * @return Returns an insance of Optional for the key. + */ + static of(key: any, checkParent?: boolean = false): Optional { + return new Optional(key, checkParent); + } +} + + +/** +* Used to inject the dependency from the parent container instead of the current one. +*/ +export class Parent extends Resolver { + /** + * Creates an instance of the Parent class. + * @param key The key to resolve from the parent container. + */ + constructor(key: any) { + super(); + this.key = key; + } + + /** + * Called by the container to load the dependency from the parent container + * @param container The container to resolve the parent from. + * @return Returns the matching instance from the parent container + */ + get(container: Container): any { + return container.parent + ? container.parent.get(this.key) + : null; + } + + /** + * Creates a Parent Resolver for the supplied key. + * @param key The key to resolve. + * @return Returns an insance of Parent for the key. + */ + static of(key : any) : Parent { + return new Parent(key); + } +} + +export class StrategyResolver { + constructor(strategy, state) { + this.strategy = strategy; + this.state = state; + } + + get(container, key) { + switch (this.strategy) { + case 0: //instance + return this.state; + case 1: //singleton + let singleton = container.invoke(this.state); + this.state = singleton; + this.strategy = 0; + return singleton; + case 2: //transient + return container.invoke(this.state); + case 3: //function + return this.state(container, key, this); + case 4: //array + return this.state[0].get(container, key); + case 5: //alias + return container.get(this.state); + default: + throw new Error('Invalid strategy: ' + this.strategy); + } + } +} /** * Used to invoke a factory method. @@ -234,64 +234,64 @@ export class FactoryActivator { } } -/** -* Used to allow functions/classes to indicate that they should be registered as transients with the container. -*/ -export class TransientRegistration { - /** - * Creates an instance of TransientRegistration. - * @param key The key to register as. - */ - constructor(key: any) { - this.key = key; - } - - /** - * Called by the container to register the annotated function/class as transient. - * @param container The container to register with. - * @param key The key to register as. - * @param fn The function to register (target of the annotation). - * @return The resolver that should to be used. - */ - createResolver(container: Container, key: any, fn: Function): Resolver { - return new StrategyResolver(2, fn); - } -} - -/** -* Used to allow functions/classes to indicate that they should be registered as singletons with the container. -*/ -export class SingletonRegistration { - /** - * Creates an instance of SingletonRegistration. - * @param key The key to register as. - */ - constructor(keyOrRegisterInChild: any, registerInChild?: boolean = false) { - if (typeof keyOrRegisterInChild === 'boolean') { - this.registerInChild = keyOrRegisterInChild; - } else { - this.key = keyOrRegisterInChild; - this.registerInChild = registerInChild; - } - } - - /** - * Called by the container to register the annotated function/class as a singleton. - * @param container The container to register with. - * @param key The key to register as. - * @param fn The function to register (target of the annotation). - * @return The resolver that should to be used. - */ - createResolver(container: Container, key: any, fn: Function): Resolver { - let resolver = new StrategyResolver(1, fn); - - if (!this.registerInChild && container !== container.root) { - container.root.registerResolver(this.key || key, resolver); - } - - return resolver; - } -} +/** +* Used to allow functions/classes to indicate that they should be registered as transients with the container. +*/ +export class TransientRegistration { + /** + * Creates an instance of TransientRegistration. + * @param key The key to register as. + */ + constructor(key: any) { + this.key = key; + } + + /** + * Called by the container to register the annotated function/class as transient. + * @param container The container to register with. + * @param key The key to register as. + * @param fn The function to register (target of the annotation). + * @return The resolver that should to be used. + */ + createResolver(container: Container, key: any, fn: Function): Resolver { + return new StrategyResolver(2, fn); + } +} + +/** +* Used to allow functions/classes to indicate that they should be registered as singletons with the container. +*/ +export class SingletonRegistration { + /** + * Creates an instance of SingletonRegistration. + * @param key The key to register as. + */ + constructor(keyOrRegisterInChild: any, registerInChild?: boolean = false) { + if (typeof keyOrRegisterInChild === 'boolean') { + this.registerInChild = keyOrRegisterInChild; + } else { + this.key = keyOrRegisterInChild; + this.registerInChild = registerInChild; + } + } + + /** + * Called by the container to register the annotated function/class as a singleton. + * @param container The container to register with. + * @param key The key to register as. + * @param fn The function to register (target of the annotation). + * @return The resolver that should to be used. + */ + createResolver(container: Container, key: any, fn: Function): Resolver { + let resolver = new StrategyResolver(1, fn); + + if (!this.registerInChild && container !== container.root) { + this.targetContainer = container.root; + } + + return resolver; + } +} const badKeyError = 'key/value cannot be null or undefined. Are you trying to inject/register something that doesn\'t exist with DI?'; export const _emptyParameters = Object.freeze([]); @@ -471,7 +471,8 @@ export class Container { resolver = new StrategyResolver(0, fn); } - this.registerResolver(key === undefined ? fn : key, resolver); + let targetContainer = resolver.targetContainer || this; + targetContainer.registerResolver(key === undefined ? fn : key, resolver); return resolver; } diff --git a/dist/commonjs/aurelia-dependency-injection.d.ts b/dist/commonjs/aurelia-dependency-injection.d.ts index e801469..0187213 100644 --- a/dist/commonjs/aurelia-dependency-injection.d.ts +++ b/dist/commonjs/aurelia-dependency-injection.d.ts @@ -3,121 +3,121 @@ declare module 'aurelia-dependency-injection' { import { metadata, decorators } from 'aurelia-metadata'; import { AggregateError } from 'aurelia-pal'; - /** - * An abstract resolver used to allow functions/classes to specify custom dependency resolution logic. + /** + * An abstract resolver used to allow functions/classes to specify custom dependency resolution logic. */ export class Resolver { - /** - * Called by the container to allow custom resolution of dependencies for a function/class. - * @param container The container to resolve from. - * @return Returns the resolved object. + /** + * Called by the container to allow custom resolution of dependencies for a function/class. + * @param container The container to resolve from. + * @return Returns the resolved object. */ get(container: Container): any; } - /** - * Used to allow functions/classes to specify lazy resolution logic. + /** + * Used to allow functions/classes to specify lazy resolution logic. */ export class Lazy extends Resolver { - /** - * Creates an instance of the Lazy class. - * @param key The key to lazily resolve. + /** + * Creates an instance of the Lazy class. + * @param key The key to lazily resolve. */ constructor(key: any); - /** - * Called by the container to lazily resolve the dependency into a lazy locator function. - * @param container The container to resolve from. - * @return Returns a function which can be invoked at a later time to obtain the actual dependency. + /** + * Called by the container to lazily resolve the dependency into a lazy locator function. + * @param container The container to resolve from. + * @return Returns a function which can be invoked at a later time to obtain the actual dependency. */ get(container: Container): any; - /** - * Creates a Lazy Resolver for the supplied key. - * @param key The key to lazily resolve. - * @return Returns an insance of Lazy for the key. + /** + * Creates a Lazy Resolver for the supplied key. + * @param key The key to lazily resolve. + * @return Returns an insance of Lazy for the key. */ static of(key: any): Lazy; } - /** - * Used to allow functions/classes to specify resolution of all matches to a key. + /** + * Used to allow functions/classes to specify resolution of all matches to a key. */ export class All extends Resolver { - /** - * Creates an instance of the All class. - * @param key The key to lazily resolve all matches for. + /** + * Creates an instance of the All class. + * @param key The key to lazily resolve all matches for. */ constructor(key: any); - /** - * Called by the container to resolve all matching dependencies as an array of instances. - * @param container The container to resolve from. - * @return Returns an array of all matching instances. + /** + * Called by the container to resolve all matching dependencies as an array of instances. + * @param container The container to resolve from. + * @return Returns an array of all matching instances. */ get(container: Container): any[]; - /** - * Creates an All Resolver for the supplied key. - * @param key The key to resolve all instances for. - * @return Returns an insance of All for the key. + /** + * Creates an All Resolver for the supplied key. + * @param key The key to resolve all instances for. + * @return Returns an insance of All for the key. */ static of(key: any): All; } - /** - * Used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. + /** + * Used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. */ export class Optional extends Resolver { - /** - * Creates an instance of the Optional class. - * @param key The key to optionally resolve for. - * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + /** + * Creates an instance of the Optional class. + * @param key The key to optionally resolve for. + * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. */ constructor(key: any, checkParent?: boolean); - /** - * Called by the container to provide optional resolution of the key. - * @param container The container to resolve from. - * @return Returns the instance if found; otherwise null. + /** + * Called by the container to provide optional resolution of the key. + * @param container The container to resolve from. + * @return Returns the instance if found; otherwise null. */ get(container: Container): any; - /** - * Creates an Optional Resolver for the supplied key. - * @param key The key to optionally resolve for. - * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. - * @return Returns an insance of Optional for the key. + /** + * Creates an Optional Resolver for the supplied key. + * @param key The key to optionally resolve for. + * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + * @return Returns an insance of Optional for the key. */ static of(key: any, checkParent?: boolean): Optional; } - /** - * Used to inject the dependency from the parent container instead of the current one. + /** + * Used to inject the dependency from the parent container instead of the current one. */ export class Parent extends Resolver { - /** - * Creates an instance of the Parent class. - * @param key The key to resolve from the parent container. + /** + * Creates an instance of the Parent class. + * @param key The key to resolve from the parent container. */ constructor(key: any); - /** - * Called by the container to load the dependency from the parent container - * @param container The container to resolve the parent from. - * @return Returns the matching instance from the parent container + /** + * Called by the container to load the dependency from the parent container + * @param container The container to resolve the parent from. + * @return Returns the matching instance from the parent container */ get(container: Container): any; - /** - * Creates a Parent Resolver for the supplied key. - * @param key The key to resolve. - * @return Returns an insance of Parent for the key. + /** + * Creates a Parent Resolver for the supplied key. + * @param key The key to resolve. + * @return Returns an insance of Parent for the key. */ static of(key: any): Parent; } @@ -154,44 +154,44 @@ declare module 'aurelia-dependency-injection' { invokeWithDynamicDependencies(container: any, fn: any, keys: any, deps: any): any; } - /** - * Used to allow functions/classes to indicate that they should be registered as transients with the container. + /** + * Used to allow functions/classes to indicate that they should be registered as transients with the container. */ export class TransientRegistration { - /** - * Creates an instance of TransientRegistration. - * @param key The key to register as. + /** + * Creates an instance of TransientRegistration. + * @param key The key to register as. */ constructor(key: any); - /** - * Called by the container to register the annotated function/class as transient. - * @param container The container to register with. - * @param key The key to register as. - * @param fn The function to register (target of the annotation). - * @return The resolver that should to be used. + /** + * Called by the container to register the annotated function/class as transient. + * @param container The container to register with. + * @param key The key to register as. + * @param fn The function to register (target of the annotation). + * @return The resolver that should to be used. */ createResolver(container: Container, key: any, fn: Function): Resolver; } - /** - * Used to allow functions/classes to indicate that they should be registered as singletons with the container. + /** + * Used to allow functions/classes to indicate that they should be registered as singletons with the container. */ export class SingletonRegistration { - /** - * Creates an instance of SingletonRegistration. - * @param key The key to register as. + /** + * Creates an instance of SingletonRegistration. + * @param key The key to register as. */ constructor(keyOrRegisterInChild: any, registerInChild?: boolean); - /** - * Called by the container to register the annotated function/class as a singleton. - * @param container The container to register with. - * @param key The key to register as. - * @param fn The function to register (target of the annotation). - * @return The resolver that should to be used. + /** + * Called by the container to register the annotated function/class as a singleton. + * @param container The container to register with. + * @param key The key to register as. + * @param fn The function to register (target of the annotation). + * @return The resolver that should to be used. */ createResolver(container: Container, key: any, fn: Function): Resolver; } diff --git a/dist/commonjs/aurelia-dependency-injection.js b/dist/commonjs/aurelia-dependency-injection.js index bdfb314..74f6098 100644 --- a/dist/commonjs/aurelia-dependency-injection.js +++ b/dist/commonjs/aurelia-dependency-injection.js @@ -254,7 +254,7 @@ var SingletonRegistration = (function () { var resolver = new StrategyResolver(1, fn); if (!this.registerInChild && container !== container.root) { - container.root.registerResolver(this.key || key, resolver); + this.targetContainer = container.root; } return resolver; @@ -395,7 +395,8 @@ var Container = (function () { resolver = new StrategyResolver(0, fn); } - this.registerResolver(key === undefined ? fn : key, resolver); + var targetContainer = resolver.targetContainer || this; + targetContainer.registerResolver(key === undefined ? fn : key, resolver); return resolver; }; diff --git a/dist/es6/aurelia-dependency-injection.d.ts b/dist/es6/aurelia-dependency-injection.d.ts index e801469..0187213 100644 --- a/dist/es6/aurelia-dependency-injection.d.ts +++ b/dist/es6/aurelia-dependency-injection.d.ts @@ -3,121 +3,121 @@ declare module 'aurelia-dependency-injection' { import { metadata, decorators } from 'aurelia-metadata'; import { AggregateError } from 'aurelia-pal'; - /** - * An abstract resolver used to allow functions/classes to specify custom dependency resolution logic. + /** + * An abstract resolver used to allow functions/classes to specify custom dependency resolution logic. */ export class Resolver { - /** - * Called by the container to allow custom resolution of dependencies for a function/class. - * @param container The container to resolve from. - * @return Returns the resolved object. + /** + * Called by the container to allow custom resolution of dependencies for a function/class. + * @param container The container to resolve from. + * @return Returns the resolved object. */ get(container: Container): any; } - /** - * Used to allow functions/classes to specify lazy resolution logic. + /** + * Used to allow functions/classes to specify lazy resolution logic. */ export class Lazy extends Resolver { - /** - * Creates an instance of the Lazy class. - * @param key The key to lazily resolve. + /** + * Creates an instance of the Lazy class. + * @param key The key to lazily resolve. */ constructor(key: any); - /** - * Called by the container to lazily resolve the dependency into a lazy locator function. - * @param container The container to resolve from. - * @return Returns a function which can be invoked at a later time to obtain the actual dependency. + /** + * Called by the container to lazily resolve the dependency into a lazy locator function. + * @param container The container to resolve from. + * @return Returns a function which can be invoked at a later time to obtain the actual dependency. */ get(container: Container): any; - /** - * Creates a Lazy Resolver for the supplied key. - * @param key The key to lazily resolve. - * @return Returns an insance of Lazy for the key. + /** + * Creates a Lazy Resolver for the supplied key. + * @param key The key to lazily resolve. + * @return Returns an insance of Lazy for the key. */ static of(key: any): Lazy; } - /** - * Used to allow functions/classes to specify resolution of all matches to a key. + /** + * Used to allow functions/classes to specify resolution of all matches to a key. */ export class All extends Resolver { - /** - * Creates an instance of the All class. - * @param key The key to lazily resolve all matches for. + /** + * Creates an instance of the All class. + * @param key The key to lazily resolve all matches for. */ constructor(key: any); - /** - * Called by the container to resolve all matching dependencies as an array of instances. - * @param container The container to resolve from. - * @return Returns an array of all matching instances. + /** + * Called by the container to resolve all matching dependencies as an array of instances. + * @param container The container to resolve from. + * @return Returns an array of all matching instances. */ get(container: Container): any[]; - /** - * Creates an All Resolver for the supplied key. - * @param key The key to resolve all instances for. - * @return Returns an insance of All for the key. + /** + * Creates an All Resolver for the supplied key. + * @param key The key to resolve all instances for. + * @return Returns an insance of All for the key. */ static of(key: any): All; } - /** - * Used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. + /** + * Used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. */ export class Optional extends Resolver { - /** - * Creates an instance of the Optional class. - * @param key The key to optionally resolve for. - * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + /** + * Creates an instance of the Optional class. + * @param key The key to optionally resolve for. + * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. */ constructor(key: any, checkParent?: boolean); - /** - * Called by the container to provide optional resolution of the key. - * @param container The container to resolve from. - * @return Returns the instance if found; otherwise null. + /** + * Called by the container to provide optional resolution of the key. + * @param container The container to resolve from. + * @return Returns the instance if found; otherwise null. */ get(container: Container): any; - /** - * Creates an Optional Resolver for the supplied key. - * @param key The key to optionally resolve for. - * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. - * @return Returns an insance of Optional for the key. + /** + * Creates an Optional Resolver for the supplied key. + * @param key The key to optionally resolve for. + * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + * @return Returns an insance of Optional for the key. */ static of(key: any, checkParent?: boolean): Optional; } - /** - * Used to inject the dependency from the parent container instead of the current one. + /** + * Used to inject the dependency from the parent container instead of the current one. */ export class Parent extends Resolver { - /** - * Creates an instance of the Parent class. - * @param key The key to resolve from the parent container. + /** + * Creates an instance of the Parent class. + * @param key The key to resolve from the parent container. */ constructor(key: any); - /** - * Called by the container to load the dependency from the parent container - * @param container The container to resolve the parent from. - * @return Returns the matching instance from the parent container + /** + * Called by the container to load the dependency from the parent container + * @param container The container to resolve the parent from. + * @return Returns the matching instance from the parent container */ get(container: Container): any; - /** - * Creates a Parent Resolver for the supplied key. - * @param key The key to resolve. - * @return Returns an insance of Parent for the key. + /** + * Creates a Parent Resolver for the supplied key. + * @param key The key to resolve. + * @return Returns an insance of Parent for the key. */ static of(key: any): Parent; } @@ -154,44 +154,44 @@ declare module 'aurelia-dependency-injection' { invokeWithDynamicDependencies(container: any, fn: any, keys: any, deps: any): any; } - /** - * Used to allow functions/classes to indicate that they should be registered as transients with the container. + /** + * Used to allow functions/classes to indicate that they should be registered as transients with the container. */ export class TransientRegistration { - /** - * Creates an instance of TransientRegistration. - * @param key The key to register as. + /** + * Creates an instance of TransientRegistration. + * @param key The key to register as. */ constructor(key: any); - /** - * Called by the container to register the annotated function/class as transient. - * @param container The container to register with. - * @param key The key to register as. - * @param fn The function to register (target of the annotation). - * @return The resolver that should to be used. + /** + * Called by the container to register the annotated function/class as transient. + * @param container The container to register with. + * @param key The key to register as. + * @param fn The function to register (target of the annotation). + * @return The resolver that should to be used. */ createResolver(container: Container, key: any, fn: Function): Resolver; } - /** - * Used to allow functions/classes to indicate that they should be registered as singletons with the container. + /** + * Used to allow functions/classes to indicate that they should be registered as singletons with the container. */ export class SingletonRegistration { - /** - * Creates an instance of SingletonRegistration. - * @param key The key to register as. + /** + * Creates an instance of SingletonRegistration. + * @param key The key to register as. */ constructor(keyOrRegisterInChild: any, registerInChild?: boolean); - /** - * Called by the container to register the annotated function/class as a singleton. - * @param container The container to register with. - * @param key The key to register as. - * @param fn The function to register (target of the annotation). - * @return The resolver that should to be used. + /** + * Called by the container to register the annotated function/class as a singleton. + * @param container The container to register with. + * @param key The key to register as. + * @param fn The function to register (target of the annotation). + * @return The resolver that should to be used. */ createResolver(container: Container, key: any, fn: Function): Resolver; } diff --git a/dist/es6/aurelia-dependency-injection.js b/dist/es6/aurelia-dependency-injection.js index 5dab32b..02944cc 100644 --- a/dist/es6/aurelia-dependency-injection.js +++ b/dist/es6/aurelia-dependency-injection.js @@ -2,188 +2,188 @@ import 'core-js'; import {metadata,decorators} from 'aurelia-metadata'; import {AggregateError} from 'aurelia-pal'; -/** -* An abstract resolver used to allow functions/classes to specify custom dependency resolution logic. -*/ -export class Resolver { - /** - * Called by the container to allow custom resolution of dependencies for a function/class. - * @param container The container to resolve from. - * @return Returns the resolved object. - */ - get(container: Container): any { - throw new Error('A custom Resolver must implement get(container) and return the resolved instance(s).'); - } -} - -/** -* Used to allow functions/classes to specify lazy resolution logic. -*/ -export class Lazy extends Resolver { - /** - * Creates an instance of the Lazy class. - * @param key The key to lazily resolve. - */ - constructor(key: any) { - super(); - this.key = key; - } - - /** - * Called by the container to lazily resolve the dependency into a lazy locator function. - * @param container The container to resolve from. - * @return Returns a function which can be invoked at a later time to obtain the actual dependency. - */ - get(container: Container): any { - return () => { - return container.get(this.key); - }; - } - - /** - * Creates a Lazy Resolver for the supplied key. - * @param key The key to lazily resolve. - * @return Returns an insance of Lazy for the key. - */ - static of(key: any): Lazy { - return new Lazy(key); - } -} - -/** -* Used to allow functions/classes to specify resolution of all matches to a key. -*/ -export class All extends Resolver { - /** - * Creates an instance of the All class. - * @param key The key to lazily resolve all matches for. - */ - constructor(key: any) { - super(); - this.key = key; - } - - /** - * Called by the container to resolve all matching dependencies as an array of instances. - * @param container The container to resolve from. - * @return Returns an array of all matching instances. - */ - get(container: Container): any[] { - return container.getAll(this.key); - } - - /** - * Creates an All Resolver for the supplied key. - * @param key The key to resolve all instances for. - * @return Returns an insance of All for the key. - */ - static of(key: any): All { - return new All(key); - } -} - -/** -* Used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. -*/ -export class Optional extends Resolver { - /** - * Creates an instance of the Optional class. - * @param key The key to optionally resolve for. - * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. - */ - constructor(key: any, checkParent?: boolean = false) { - super(); - this.key = key; - this.checkParent = checkParent; - } - - /** - * Called by the container to provide optional resolution of the key. - * @param container The container to resolve from. - * @return Returns the instance if found; otherwise null. - */ - get(container: Container): any { - if (container.hasResolver(this.key, this.checkParent)) { - return container.get(this.key); - } - - return null; - } - - /** - * Creates an Optional Resolver for the supplied key. - * @param key The key to optionally resolve for. - * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. - * @return Returns an insance of Optional for the key. - */ - static of(key: any, checkParent?: boolean = false): Optional { - return new Optional(key, checkParent); - } -} - - -/** -* Used to inject the dependency from the parent container instead of the current one. -*/ -export class Parent extends Resolver { - /** - * Creates an instance of the Parent class. - * @param key The key to resolve from the parent container. - */ - constructor(key: any) { - super(); - this.key = key; - } - - /** - * Called by the container to load the dependency from the parent container - * @param container The container to resolve the parent from. - * @return Returns the matching instance from the parent container - */ - get(container: Container): any { - return container.parent - ? container.parent.get(this.key) - : null; - } - - /** - * Creates a Parent Resolver for the supplied key. - * @param key The key to resolve. - * @return Returns an insance of Parent for the key. - */ - static of(key : any) : Parent { - return new Parent(key); - } -} - -export class StrategyResolver { - constructor(strategy, state) { - this.strategy = strategy; - this.state = state; - } - - get(container, key) { - switch (this.strategy) { - case 0: //instance - return this.state; - case 1: //singleton - let singleton = container.invoke(this.state); - this.state = singleton; - this.strategy = 0; - return singleton; - case 2: //transient - return container.invoke(this.state); - case 3: //function - return this.state(container, key, this); - case 4: //array - return this.state[0].get(container, key); - case 5: //alias - return container.get(this.state); - default: - throw new Error('Invalid strategy: ' + this.strategy); - } - } -} +/** +* An abstract resolver used to allow functions/classes to specify custom dependency resolution logic. +*/ +export class Resolver { + /** + * Called by the container to allow custom resolution of dependencies for a function/class. + * @param container The container to resolve from. + * @return Returns the resolved object. + */ + get(container: Container): any { + throw new Error('A custom Resolver must implement get(container) and return the resolved instance(s).'); + } +} + +/** +* Used to allow functions/classes to specify lazy resolution logic. +*/ +export class Lazy extends Resolver { + /** + * Creates an instance of the Lazy class. + * @param key The key to lazily resolve. + */ + constructor(key: any) { + super(); + this.key = key; + } + + /** + * Called by the container to lazily resolve the dependency into a lazy locator function. + * @param container The container to resolve from. + * @return Returns a function which can be invoked at a later time to obtain the actual dependency. + */ + get(container: Container): any { + return () => { + return container.get(this.key); + }; + } + + /** + * Creates a Lazy Resolver for the supplied key. + * @param key The key to lazily resolve. + * @return Returns an insance of Lazy for the key. + */ + static of(key: any): Lazy { + return new Lazy(key); + } +} + +/** +* Used to allow functions/classes to specify resolution of all matches to a key. +*/ +export class All extends Resolver { + /** + * Creates an instance of the All class. + * @param key The key to lazily resolve all matches for. + */ + constructor(key: any) { + super(); + this.key = key; + } + + /** + * Called by the container to resolve all matching dependencies as an array of instances. + * @param container The container to resolve from. + * @return Returns an array of all matching instances. + */ + get(container: Container): any[] { + return container.getAll(this.key); + } + + /** + * Creates an All Resolver for the supplied key. + * @param key The key to resolve all instances for. + * @return Returns an insance of All for the key. + */ + static of(key: any): All { + return new All(key); + } +} + +/** +* Used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. +*/ +export class Optional extends Resolver { + /** + * Creates an instance of the Optional class. + * @param key The key to optionally resolve for. + * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + */ + constructor(key: any, checkParent?: boolean = false) { + super(); + this.key = key; + this.checkParent = checkParent; + } + + /** + * Called by the container to provide optional resolution of the key. + * @param container The container to resolve from. + * @return Returns the instance if found; otherwise null. + */ + get(container: Container): any { + if (container.hasResolver(this.key, this.checkParent)) { + return container.get(this.key); + } + + return null; + } + + /** + * Creates an Optional Resolver for the supplied key. + * @param key The key to optionally resolve for. + * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + * @return Returns an insance of Optional for the key. + */ + static of(key: any, checkParent?: boolean = false): Optional { + return new Optional(key, checkParent); + } +} + + +/** +* Used to inject the dependency from the parent container instead of the current one. +*/ +export class Parent extends Resolver { + /** + * Creates an instance of the Parent class. + * @param key The key to resolve from the parent container. + */ + constructor(key: any) { + super(); + this.key = key; + } + + /** + * Called by the container to load the dependency from the parent container + * @param container The container to resolve the parent from. + * @return Returns the matching instance from the parent container + */ + get(container: Container): any { + return container.parent + ? container.parent.get(this.key) + : null; + } + + /** + * Creates a Parent Resolver for the supplied key. + * @param key The key to resolve. + * @return Returns an insance of Parent for the key. + */ + static of(key : any) : Parent { + return new Parent(key); + } +} + +export class StrategyResolver { + constructor(strategy, state) { + this.strategy = strategy; + this.state = state; + } + + get(container, key) { + switch (this.strategy) { + case 0: //instance + return this.state; + case 1: //singleton + let singleton = container.invoke(this.state); + this.state = singleton; + this.strategy = 0; + return singleton; + case 2: //transient + return container.invoke(this.state); + case 3: //function + return this.state(container, key, this); + case 4: //array + return this.state[0].get(container, key); + case 5: //alias + return container.get(this.state); + default: + throw new Error('Invalid strategy: ' + this.strategy); + } + } +} /** * Used to invoke a factory method. @@ -234,64 +234,64 @@ export class FactoryActivator { } } -/** -* Used to allow functions/classes to indicate that they should be registered as transients with the container. -*/ -export class TransientRegistration { - /** - * Creates an instance of TransientRegistration. - * @param key The key to register as. - */ - constructor(key: any) { - this.key = key; - } - - /** - * Called by the container to register the annotated function/class as transient. - * @param container The container to register with. - * @param key The key to register as. - * @param fn The function to register (target of the annotation). - * @return The resolver that should to be used. - */ - createResolver(container: Container, key: any, fn: Function): Resolver { - return new StrategyResolver(2, fn); - } -} - -/** -* Used to allow functions/classes to indicate that they should be registered as singletons with the container. -*/ -export class SingletonRegistration { - /** - * Creates an instance of SingletonRegistration. - * @param key The key to register as. - */ - constructor(keyOrRegisterInChild: any, registerInChild?: boolean = false) { - if (typeof keyOrRegisterInChild === 'boolean') { - this.registerInChild = keyOrRegisterInChild; - } else { - this.key = keyOrRegisterInChild; - this.registerInChild = registerInChild; - } - } - - /** - * Called by the container to register the annotated function/class as a singleton. - * @param container The container to register with. - * @param key The key to register as. - * @param fn The function to register (target of the annotation). - * @return The resolver that should to be used. - */ - createResolver(container: Container, key: any, fn: Function): Resolver { - let resolver = new StrategyResolver(1, fn); - - if (!this.registerInChild && container !== container.root) { - container.root.registerResolver(this.key || key, resolver); - } - - return resolver; - } -} +/** +* Used to allow functions/classes to indicate that they should be registered as transients with the container. +*/ +export class TransientRegistration { + /** + * Creates an instance of TransientRegistration. + * @param key The key to register as. + */ + constructor(key: any) { + this.key = key; + } + + /** + * Called by the container to register the annotated function/class as transient. + * @param container The container to register with. + * @param key The key to register as. + * @param fn The function to register (target of the annotation). + * @return The resolver that should to be used. + */ + createResolver(container: Container, key: any, fn: Function): Resolver { + return new StrategyResolver(2, fn); + } +} + +/** +* Used to allow functions/classes to indicate that they should be registered as singletons with the container. +*/ +export class SingletonRegistration { + /** + * Creates an instance of SingletonRegistration. + * @param key The key to register as. + */ + constructor(keyOrRegisterInChild: any, registerInChild?: boolean = false) { + if (typeof keyOrRegisterInChild === 'boolean') { + this.registerInChild = keyOrRegisterInChild; + } else { + this.key = keyOrRegisterInChild; + this.registerInChild = registerInChild; + } + } + + /** + * Called by the container to register the annotated function/class as a singleton. + * @param container The container to register with. + * @param key The key to register as. + * @param fn The function to register (target of the annotation). + * @return The resolver that should to be used. + */ + createResolver(container: Container, key: any, fn: Function): Resolver { + let resolver = new StrategyResolver(1, fn); + + if (!this.registerInChild && container !== container.root) { + this.targetContainer = container.root; + } + + return resolver; + } +} const badKeyError = 'key/value cannot be null or undefined. Are you trying to inject/register something that doesn\'t exist with DI?'; export const _emptyParameters = Object.freeze([]); @@ -471,7 +471,8 @@ export class Container { resolver = new StrategyResolver(0, fn); } - this.registerResolver(key === undefined ? fn : key, resolver); + let targetContainer = resolver.targetContainer || this; + targetContainer.registerResolver(key === undefined ? fn : key, resolver); return resolver; } diff --git a/dist/system/aurelia-dependency-injection.d.ts b/dist/system/aurelia-dependency-injection.d.ts index e801469..0187213 100644 --- a/dist/system/aurelia-dependency-injection.d.ts +++ b/dist/system/aurelia-dependency-injection.d.ts @@ -3,121 +3,121 @@ declare module 'aurelia-dependency-injection' { import { metadata, decorators } from 'aurelia-metadata'; import { AggregateError } from 'aurelia-pal'; - /** - * An abstract resolver used to allow functions/classes to specify custom dependency resolution logic. + /** + * An abstract resolver used to allow functions/classes to specify custom dependency resolution logic. */ export class Resolver { - /** - * Called by the container to allow custom resolution of dependencies for a function/class. - * @param container The container to resolve from. - * @return Returns the resolved object. + /** + * Called by the container to allow custom resolution of dependencies for a function/class. + * @param container The container to resolve from. + * @return Returns the resolved object. */ get(container: Container): any; } - /** - * Used to allow functions/classes to specify lazy resolution logic. + /** + * Used to allow functions/classes to specify lazy resolution logic. */ export class Lazy extends Resolver { - /** - * Creates an instance of the Lazy class. - * @param key The key to lazily resolve. + /** + * Creates an instance of the Lazy class. + * @param key The key to lazily resolve. */ constructor(key: any); - /** - * Called by the container to lazily resolve the dependency into a lazy locator function. - * @param container The container to resolve from. - * @return Returns a function which can be invoked at a later time to obtain the actual dependency. + /** + * Called by the container to lazily resolve the dependency into a lazy locator function. + * @param container The container to resolve from. + * @return Returns a function which can be invoked at a later time to obtain the actual dependency. */ get(container: Container): any; - /** - * Creates a Lazy Resolver for the supplied key. - * @param key The key to lazily resolve. - * @return Returns an insance of Lazy for the key. + /** + * Creates a Lazy Resolver for the supplied key. + * @param key The key to lazily resolve. + * @return Returns an insance of Lazy for the key. */ static of(key: any): Lazy; } - /** - * Used to allow functions/classes to specify resolution of all matches to a key. + /** + * Used to allow functions/classes to specify resolution of all matches to a key. */ export class All extends Resolver { - /** - * Creates an instance of the All class. - * @param key The key to lazily resolve all matches for. + /** + * Creates an instance of the All class. + * @param key The key to lazily resolve all matches for. */ constructor(key: any); - /** - * Called by the container to resolve all matching dependencies as an array of instances. - * @param container The container to resolve from. - * @return Returns an array of all matching instances. + /** + * Called by the container to resolve all matching dependencies as an array of instances. + * @param container The container to resolve from. + * @return Returns an array of all matching instances. */ get(container: Container): any[]; - /** - * Creates an All Resolver for the supplied key. - * @param key The key to resolve all instances for. - * @return Returns an insance of All for the key. + /** + * Creates an All Resolver for the supplied key. + * @param key The key to resolve all instances for. + * @return Returns an insance of All for the key. */ static of(key: any): All; } - /** - * Used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. + /** + * Used to allow functions/classes to specify an optional dependency, which will be resolved only if already registred with the container. */ export class Optional extends Resolver { - /** - * Creates an instance of the Optional class. - * @param key The key to optionally resolve for. - * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + /** + * Creates an instance of the Optional class. + * @param key The key to optionally resolve for. + * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. */ constructor(key: any, checkParent?: boolean); - /** - * Called by the container to provide optional resolution of the key. - * @param container The container to resolve from. - * @return Returns the instance if found; otherwise null. + /** + * Called by the container to provide optional resolution of the key. + * @param container The container to resolve from. + * @return Returns the instance if found; otherwise null. */ get(container: Container): any; - /** - * Creates an Optional Resolver for the supplied key. - * @param key The key to optionally resolve for. - * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. - * @return Returns an insance of Optional for the key. + /** + * Creates an Optional Resolver for the supplied key. + * @param key The key to optionally resolve for. + * @param [checkParent=false] Indicates whether or not the parent container hierarchy should be checked. + * @return Returns an insance of Optional for the key. */ static of(key: any, checkParent?: boolean): Optional; } - /** - * Used to inject the dependency from the parent container instead of the current one. + /** + * Used to inject the dependency from the parent container instead of the current one. */ export class Parent extends Resolver { - /** - * Creates an instance of the Parent class. - * @param key The key to resolve from the parent container. + /** + * Creates an instance of the Parent class. + * @param key The key to resolve from the parent container. */ constructor(key: any); - /** - * Called by the container to load the dependency from the parent container - * @param container The container to resolve the parent from. - * @return Returns the matching instance from the parent container + /** + * Called by the container to load the dependency from the parent container + * @param container The container to resolve the parent from. + * @return Returns the matching instance from the parent container */ get(container: Container): any; - /** - * Creates a Parent Resolver for the supplied key. - * @param key The key to resolve. - * @return Returns an insance of Parent for the key. + /** + * Creates a Parent Resolver for the supplied key. + * @param key The key to resolve. + * @return Returns an insance of Parent for the key. */ static of(key: any): Parent; } @@ -154,44 +154,44 @@ declare module 'aurelia-dependency-injection' { invokeWithDynamicDependencies(container: any, fn: any, keys: any, deps: any): any; } - /** - * Used to allow functions/classes to indicate that they should be registered as transients with the container. + /** + * Used to allow functions/classes to indicate that they should be registered as transients with the container. */ export class TransientRegistration { - /** - * Creates an instance of TransientRegistration. - * @param key The key to register as. + /** + * Creates an instance of TransientRegistration. + * @param key The key to register as. */ constructor(key: any); - /** - * Called by the container to register the annotated function/class as transient. - * @param container The container to register with. - * @param key The key to register as. - * @param fn The function to register (target of the annotation). - * @return The resolver that should to be used. + /** + * Called by the container to register the annotated function/class as transient. + * @param container The container to register with. + * @param key The key to register as. + * @param fn The function to register (target of the annotation). + * @return The resolver that should to be used. */ createResolver(container: Container, key: any, fn: Function): Resolver; } - /** - * Used to allow functions/classes to indicate that they should be registered as singletons with the container. + /** + * Used to allow functions/classes to indicate that they should be registered as singletons with the container. */ export class SingletonRegistration { - /** - * Creates an instance of SingletonRegistration. - * @param key The key to register as. + /** + * Creates an instance of SingletonRegistration. + * @param key The key to register as. */ constructor(keyOrRegisterInChild: any, registerInChild?: boolean); - /** - * Called by the container to register the annotated function/class as a singleton. - * @param container The container to register with. - * @param key The key to register as. - * @param fn The function to register (target of the annotation). - * @return The resolver that should to be used. + /** + * Called by the container to register the annotated function/class as a singleton. + * @param container The container to register with. + * @param key The key to register as. + * @param fn The function to register (target of the annotation). + * @return The resolver that should to be used. */ createResolver(container: Container, key: any, fn: Function): Resolver; } diff --git a/dist/system/aurelia-dependency-injection.js b/dist/system/aurelia-dependency-injection.js index 7c6d7ba..67c78de 100644 --- a/dist/system/aurelia-dependency-injection.js +++ b/dist/system/aurelia-dependency-injection.js @@ -327,7 +327,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-pal'], function (_expor var resolver = new StrategyResolver(1, fn); if (!this.registerInChild && container !== container.root) { - container.root.registerResolver(this.key || key, resolver); + this.targetContainer = container.root; } return resolver; @@ -454,7 +454,8 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-pal'], function (_expor resolver = new StrategyResolver(0, fn); } - this.registerResolver(key === undefined ? fn : key, resolver); + var targetContainer = resolver.targetContainer || this; + targetContainer.registerResolver(key === undefined ? fn : key, resolver); return resolver; }; diff --git a/src/container.js b/src/container.js index 01e955d..4ef3264 100644 --- a/src/container.js +++ b/src/container.js @@ -182,7 +182,8 @@ export class Container { resolver = new StrategyResolver(0, fn); } - this.registerResolver(key === undefined ? fn : key, resolver); + let targetContainer = resolver.targetContainer || this; + targetContainer.registerResolver(key === undefined ? fn : key, resolver); return resolver; } diff --git a/src/registrations.js b/src/registrations.js index 7a349e5..3ce9c37 100644 --- a/src/registrations.js +++ b/src/registrations.js @@ -52,7 +52,7 @@ export class SingletonRegistration { let resolver = new StrategyResolver(1, fn); if (!this.registerInChild && container !== container.root) { - container.root.registerResolver(this.key || key, resolver); + this.targetContainer = container.root; } return resolver;