aurelia-dependency-injection
Version:
A lightweight, extensible dependency injection container for JavaScript.
152 lines (140 loc) • 5.41 kB
text/typescript
import './internal';
import { Resolver } from './resolvers';
import { Container } from './container';
import { metadata } from 'aurelia-metadata';
import {
DependencyCtorOrFunctor,
PrimitiveOrDependencyCtor,
Impl,
Args,
DependencyCtor
} from './types';
/**
* Decorator: Specifies a custom registration strategy for the decorated
* class/function.
*/
export function registration<TBase, TImpl extends Impl<TBase>, TArgs extends Args<TBase>>(
value: Registration<TBase, TImpl, TArgs>) {
return (target: DependencyCtor<TBase, TImpl, TArgs>) => {
metadata.define(metadata.registration, value, target);
};
}
/**
* Decorator: Specifies to register the decorated item with a "transient"
* lifetime.
*/
export function transient<TBase, TImpl extends Impl<TBase>, TArgs extends Args<TBase>>(
key?: PrimitiveOrDependencyCtor<TBase, TImpl, TArgs>) {
return registration(new TransientRegistration<TBase, TImpl, TArgs>(key));
}
/**
* Decorator: Specifies to register the decorated item with a "singleton"
* lifetime.
*/
export function singleton(registerInChild?: boolean);
export function singleton<TBase, TImpl extends Impl<TBase>, TArgs extends Args<TBase>>(
key?: PrimitiveOrDependencyCtor<TBase, TImpl, TArgs>, registerInChild?: boolean);
export function singleton<TBase, TImpl extends Impl<TBase>, TArgs extends Args<TBase>>(
keyOrRegisterInChild?: PrimitiveOrDependencyCtor<TBase, TImpl, TArgs> | boolean, registerInChild: boolean = false) {
return registration<TBase, TImpl, TArgs>(
new SingletonRegistration<TBase, TImpl, TArgs>(keyOrRegisterInChild, registerInChild)
);
}
/**
* Customizes how a particular function is resolved by the Container.
*/
export interface Registration<
TBase,
TImpl extends Impl<TBase>,
TArgs extends Args<TBase>> {
/**
* Called by the container to register the resolver.
* @param container The container the resolver is being registered with.
* @param key The key the resolver should be registered as.
* @param fn The function to create the resolver for.
* @return The resolver that was registered.
*/
registerResolver(
container: Container,
key: PrimitiveOrDependencyCtor<TBase, TImpl, TArgs>,
fn: DependencyCtorOrFunctor<TBase, TImpl, TArgs>
): Resolver;
}
/**
* Used to allow functions/classes to indicate that they should be registered as
* transients with the container.
*/
export class TransientRegistration<TBase, TImpl extends Impl<TBase>, TArgs extends Args<TBase>>
implements Registration<TBase, TImpl, TArgs> {
/** @internal */
public _key?: PrimitiveOrDependencyCtor<TBase, TImpl, TArgs>;
/**
* Creates an instance of TransientRegistration.
* @param key The key to register as.
*/
constructor(key?: PrimitiveOrDependencyCtor<TBase, TImpl, TArgs>) {
this._key = key;
}
/**
* Called by the container to register the resolver.
* @param container The container the resolver is being registered with.
* @param key The key the resolver should be registered as.
* @param fn The function to create the resolver for.
* @return The resolver that was registered.
*/
public registerResolver(
container: Container,
key: PrimitiveOrDependencyCtor<TBase, TImpl, TArgs>,
fn: DependencyCtorOrFunctor<TBase, TImpl, TArgs>
): Resolver {
const existingResolver = container.getResolver(this._key || key);
return existingResolver === undefined
? container.registerTransient<TBase, TImpl, TArgs>(
(this._key || key) as string,
fn as DependencyCtorOrFunctor<TBase, TImpl, TArgs>)
: existingResolver;
}
}
/**
* Used to allow functions/classes to indicate that they should be registered as
* singletons with the container.
*/
export class SingletonRegistration<TBase, TImpl extends Impl<TBase>, TArgs extends Args<TBase>>
implements Registration<TBase, TImpl, TArgs> {
/** @internal */
public _registerInChild: boolean;
/** @internal */
public _key?: PrimitiveOrDependencyCtor<TBase, TImpl, TArgs>;
/**
* Creates an instance of SingletonRegistration.
* @param key The key to register as.
*/
constructor(
keyOrRegisterInChild?: PrimitiveOrDependencyCtor<TBase, TImpl, TArgs> | boolean,
registerInChild: boolean = false) {
if (typeof keyOrRegisterInChild === 'boolean') {
this._registerInChild = keyOrRegisterInChild;
} else {
this._key = keyOrRegisterInChild;
this._registerInChild = registerInChild;
}
}
/**
* Called by the container to register the resolver.
* @param container The container the resolver is being registered with.
* @param key The key the resolver should be registered as.
* @param fn The function to create the resolver for.
* @return The resolver that was registered.
*/
public registerResolver(
container: Container,
key: PrimitiveOrDependencyCtor<TBase, TImpl, TArgs>,
fn: DependencyCtorOrFunctor<TBase, TImpl, TArgs>
): Resolver {
const targetContainer = this._registerInChild ? container : container.root;
const existingResolver = targetContainer.getResolver(this._key || key);
return existingResolver === undefined
? targetContainer.registerSingleton(this._key || key, fn)
: existingResolver;
}
}