This commit is contained in:
crusader 2017-08-01 14:23:34 +09:00
parent 6a9cc22a06
commit c5358742ce
21 changed files with 199 additions and 120 deletions

View File

@ -15,7 +15,7 @@ const Configuration = (qualifier?: string | symbol ) => createDecorator('Configu
throw new Error('Cannot apply @Injectable or @Injectable stereotype decorator multiple times.'); throw new Error('Cannot apply @Injectable or @Injectable stereotype decorator multiple times.');
} }
configurationDefinition = getConfigurationDefinition(target, true); configurationDefinition = getConfigurationDefinition(target.prototype, true);
configurationDefinition.Stereotype = InjectableSterotype.CONFIGURATION; configurationDefinition.Stereotype = InjectableSterotype.CONFIGURATION;
configurationDefinition.Qualifier = validateQualifier(target.prototype, qualifier); configurationDefinition.Qualifier = validateQualifier(target.prototype, qualifier);

View File

@ -1,6 +1,8 @@
import { ClassType, PropertyType } from '@loafer/core/constants';
interface PouchConfig { interface PouchConfig {
qualifier?: string | symbol; qualifier?: PropertyType;
type?: any; type?: ClassType;
} }
export default PouchConfig; export default PouchConfig;

View File

@ -15,7 +15,7 @@ const Service = (qualifier?: string | symbol ) => createDecorator('Service', {
throw new Error('Cannot apply @Injectable or @Injectable stereotype decorator multiple times.'); throw new Error('Cannot apply @Injectable or @Injectable stereotype decorator multiple times.');
} }
injectableDefinition = getInjectableDefinition(target, true); injectableDefinition = getInjectableDefinition(target.prototype, true);
injectableDefinition.Stereotype = InjectableSterotype.SERVICE; injectableDefinition.Stereotype = InjectableSterotype.SERVICE;
injectableDefinition.Qualifier = validateQualifier(target.prototype, qualifier); injectableDefinition.Qualifier = validateQualifier(target.prototype, qualifier);

View File

@ -1,20 +1,20 @@
import { DESIGN_RETURNTYPE } from '@loafer/core/constants'; import { ClassType, DESIGN_RETURNTYPE, PropertyType } from '@loafer/core/constants';
import InjectableDefinition from '@loafer/context/definition/InjectableDefinition'; import InjectableDefinition from '@loafer/context/definition/InjectableDefinition';
import PouchConfig from '@loafer/context/decorator/PouchConfig'; import PouchConfig from '@loafer/context/decorator/PouchConfig';
class ConfigurationDefinition extends InjectableDefinition { class ConfigurationDefinition extends InjectableDefinition {
protected _qualifier: string | symbol = undefined; protected _qualifier: PropertyType = undefined;
protected _pouchMap: Map<string, PouchConfig>; protected _pouchMap: Map<string, PouchConfig>;
public constructor(type: Object) { public constructor(clazz: ClassType) {
super(type); super(clazz);
} }
public addPouch(propertyKey: string, pouchConfig: PouchConfig): void { public addPouch(propertyKey: string, pouchConfig: PouchConfig): void {
if (undefined === this._pouchMap) { if (undefined === this._pouchMap) {
this._pouchMap = new Map(); this._pouchMap = new Map();
} }
let returnType: any = Reflect.getMetadata(DESIGN_RETURNTYPE, this._type, propertyKey); let returnType: any = Reflect.getMetadata(DESIGN_RETURNTYPE, this._clazz, propertyKey);
if (undefined === pouchConfig.type) { if (undefined === pouchConfig.type) {
pouchConfig.type = returnType; pouchConfig.type = returnType;

View File

@ -1,21 +1,22 @@
import { ClassType, PropertyType } from '@loafer/core/constants';
import PouchDefinition from '@loafer/pouches/factory/config/PouchDefinition'; import PouchDefinition from '@loafer/pouches/factory/config/PouchDefinition';
import { InjectableSterotype, PouchScope } from '@loafer/pouches/constants'; import { InjectableSterotype, PouchScope } from '@loafer/pouches/constants';
class InjectableDefinition implements PouchDefinition { class InjectableDefinition implements PouchDefinition {
protected _type: Object; protected _clazz: ClassType;
protected _stereotype: InjectableSterotype; protected _stereotype: InjectableSterotype;
protected _scope: PouchScope = PouchScope.SINGLETON; protected _scope: PouchScope = PouchScope.SINGLETON;
protected _qualifier: string | symbol = undefined; protected _qualifier: PropertyType = undefined;
protected _postConstruct: Set<string> = undefined; protected _postConstruct: Set<string> = undefined;
protected _preDestroy: Set<string> = undefined; protected _preDestroy: Set<string> = undefined;
public constructor(type: Object) { public constructor(clazz: ClassType) {
this._type = type; this._clazz = clazz;
this._stereotype = InjectableSterotype.INJECTABLE; this._stereotype = InjectableSterotype.INJECTABLE;
} }
public get Type(): Object { public get Clazz(): ClassType {
return this._type; return this._clazz;
} }
public get Stereotype(): InjectableSterotype { public get Stereotype(): InjectableSterotype {
@ -34,11 +35,11 @@ class InjectableDefinition implements PouchDefinition {
this._scope = scope; this._scope = scope;
} }
public get Qualifier(): string | symbol { public get Qualifier(): PropertyType {
return this._qualifier; return this._qualifier;
} }
public set Qualifier(qualifier: string | symbol) { public set Qualifier(qualifier: PropertyType) {
this._qualifier = qualifier; this._qualifier = qualifier;
} }

View File

@ -1,5 +1,6 @@
import { import {
Construtorable, ClassType,
PropertyType,
} from '@loafer/core/constants'; } from '@loafer/core/constants';
import AppContext from '@loafer/context/AppContext'; import AppContext from '@loafer/context/AppContext';
@ -17,12 +18,11 @@ class DefaultAppContext implements AppContext {
return this.pouchFactory; return this.pouchFactory;
} }
public getPouch<T>(type: Construtorable<T>, ...args: any[]): T { public getPouch(qualifier: PropertyType, clazz: ClassType, ...args: any[]): any {
return this.pouchFactory.getPouch(type, args); return this.pouchFactory.getPouch(qualifier, clazz, args);
} }
public getPouchByType(clazz: ClassType, qualifier: PropertyType, ...args: any[]): any {
public getPouchByQualifier<T>(type: Construtorable<T>, qualifier: string | symbol, ...args: any[]): T { return this.pouchFactory.getPouchByType(clazz, qualifier, args);
return this.pouchFactory.getPouchByQualifier(type, qualifier, args);
} }
} }

View File

@ -1,6 +1,7 @@
import { ClassType } from '@loafer/core/constants';
import getClassMetadata from '@loafer/core/util/metadata/getClassMetadata'; import getClassMetadata from '@loafer/core/util/metadata/getClassMetadata';
import { CONTEXT_INJECTABLE_DEFINITION } from '@loafer/context/constants'; import { CONTEXT_INJECTABLE_DEFINITION } from '@loafer/context/constants';
import ConfigurationDefinition from '@loafer/context/definition/ConfigurationDefinition'; import ConfigurationDefinition from '@loafer/context/definition/ConfigurationDefinition';
export const getConfigurationDefinition = (target: Object, isCreate: boolean = false) => export const getConfigurationDefinition = (clazz: ClassType, isCreate: boolean = false) =>
getClassMetadata(target, CONTEXT_INJECTABLE_DEFINITION, ConfigurationDefinition, isCreate); getClassMetadata(clazz, CONTEXT_INJECTABLE_DEFINITION, ConfigurationDefinition, isCreate);

View File

@ -1,6 +1,7 @@
import { ClassType } from '@loafer/core/constants';
import getClassMetadata from '@loafer/core/util/metadata/getClassMetadata'; import getClassMetadata from '@loafer/core/util/metadata/getClassMetadata';
import { CONTEXT_INJECTABLE_DEFINITION } from '@loafer/context/constants'; import { CONTEXT_INJECTABLE_DEFINITION } from '@loafer/context/constants';
import InjectableDefinition from '@loafer/context/definition/InjectableDefinition'; import InjectableDefinition from '@loafer/context/definition/InjectableDefinition';
export const getInjectableDefinition = (target: Object, isCreate: boolean = false) => export const getInjectableDefinition = (clazz: ClassType, isCreate: boolean = false) =>
getClassMetadata(target, CONTEXT_INJECTABLE_DEFINITION, InjectableDefinition, isCreate); getClassMetadata(clazz, CONTEXT_INJECTABLE_DEFINITION, InjectableDefinition, isCreate);

View File

@ -1,4 +1,6 @@
export type Construtorable<T> = {new(...args: any[]): T}; export type Construtorable<T> = {new(...args: any[]): T};
export type ClassType = Object;
export type PropertyType = string | symbol;
export enum DecoratorType { export enum DecoratorType {
CLASS, CLASS,

View File

@ -1,21 +1,25 @@
export type MetadataDefinable<T> = {new(target: Function): T}; import {
ClassType,
} from '@loafer/core/constants';
const getClassMetadata = <DefinitionType>(target: Object, export type MetadataDefinable<T> = {new(clazz: ClassType): T};
const getClassMetadata = <DefinitionType>(clazz: ClassType,
metadataKey: any, metadataKey: any,
definitionType: MetadataDefinable<DefinitionType>, definitionType: MetadataDefinable<DefinitionType>,
isCreate: boolean = false): DefinitionType => { isCreate: boolean = false): DefinitionType => {
let definition: DefinitionType; let definition: DefinitionType;
if (Reflect.hasOwnMetadata(metadataKey, target) !== true) { if (Reflect.hasOwnMetadata(metadataKey, clazz) !== true) {
if (!isCreate) { if (!isCreate) {
return undefined; return undefined;
} }
definition = Object.create(definitionType.prototype); definition = Object.create(definitionType.prototype);
definition.constructor.call(definition, target); definition.constructor.call(definition, clazz);
Reflect.defineMetadata(metadataKey, definition, target); Reflect.defineMetadata(metadataKey, definition, clazz);
} else { } else {
definition = Reflect.getMetadata(metadataKey, target); definition = Reflect.getMetadata(metadataKey, clazz);
} }
return definition; return definition;
}; };

View File

@ -1,7 +1,9 @@
import { ClassType, PropertyType } from '@loafer/core/constants';
interface InjectConfig { interface InjectConfig {
qualifier?: string | symbol; qualifier?: PropertyType;
required?: boolean; required?: boolean;
type?: any; clazz?: ClassType;
} }
export default InjectConfig; export default InjectConfig;

View File

@ -1,33 +1,39 @@
import {
ClassType,
DecoratorType,
DESIGN_PARAMTYPES,
DESIGN_TYPE,
PropertyType,
} from '@loafer/core/constants';
import { InjectSterotype } from '@loafer/pouches/constants'; import { InjectSterotype } from '@loafer/pouches/constants';
import { validateQualifier } from '@loafer/pouches/util/qualifier'; import { validateQualifier } from '@loafer/pouches/util/qualifier';
import InjectConfig from '@loafer/pouches/decorator/InjectConfig'; import InjectConfig from '@loafer/pouches/decorator/InjectConfig';
import * as CoreConstants from '@loafer/core/constants';
export interface InjectItem { export interface InjectItem {
stereotype: InjectSterotype; stereotype: InjectSterotype;
decoratorType: CoreConstants.DecoratorType; decoratorType: DecoratorType;
propertyConfig?: InjectConfig; propertyConfig?: InjectConfig;
parameterConfigMap?: Map<number, InjectConfig>; parameterConfigMap?: Map<number, InjectConfig>;
} }
class InjectDefinition { class InjectDefinition {
protected target: Object; protected clazz: ClassType;
protected injectMap: Map<string | symbol, InjectItem>; protected injectMap: Map<PropertyType, InjectItem>;
public constructor(target: Object) { public constructor(clazz: ClassType) {
this.target = target; this.clazz = clazz;
this.injectMap = new Map(); this.injectMap = new Map();
} }
public get injectors(): Map<string | symbol, InjectItem> { public get injectors(): Map<PropertyType, InjectItem> {
return this.injectMap; return this.injectMap;
} }
/** /**
* addInject * addInject
*/ */
public addInject(injectConfig: InjectConfig, propertyKey: string | symbol, parameterIndex?: number): void { public addInject(injectConfig: InjectConfig, propertyKey: PropertyType, parameterIndex?: number): void {
injectConfig.qualifier = validateQualifier(this.target, injectConfig.qualifier); injectConfig.qualifier = validateQualifier(this.clazz, injectConfig.qualifier);
if (undefined === injectConfig.required) { if (undefined === injectConfig.required) {
injectConfig.required = false; injectConfig.required = false;
} }
@ -42,7 +48,7 @@ class InjectDefinition {
/** /**
* addValue * addValue
*/ */
public addValue(value: string, propertyKey: string | symbol, parameterIndex?: number): void { public addValue(value: string, propertyKey: PropertyType, parameterIndex?: number): void {
if(typeof parameterIndex === 'number') { if(typeof parameterIndex === 'number') {
this.addValueParameter(value, propertyKey, parameterIndex); this.addValueParameter(value, propertyKey, parameterIndex);
} else { } else {
@ -50,22 +56,22 @@ class InjectDefinition {
} }
} }
private addValueProperty(value: string, propertyKey: string | symbol): void { private addValueProperty(value: string, propertyKey: PropertyType): void {
return; return;
} }
private addValueParameter(value: string, propertyKey: string | symbol, parameterIndex: number): void { private addValueParameter(value: string, propertyKey: PropertyType, parameterIndex: number): void {
return; return;
} }
private addInjectParameter(injectConfig: InjectConfig, private addInjectParameter(injectConfig: InjectConfig,
propertyKey: string | symbol, parameterIndex: number): void { propertyKey: PropertyType, parameterIndex: number): void {
let injectItem: InjectItem; let injectItem: InjectItem;
let parameterTypes: any[] = Reflect.getMetadata(CoreConstants.DESIGN_PARAMTYPES, this.target, propertyKey); let parameterTypes: any[] = Reflect.getMetadata(DESIGN_PARAMTYPES, this.clazz, propertyKey);
if (undefined === injectConfig.type) { if (undefined === injectConfig.clazz) {
injectConfig.type = parameterTypes[parameterIndex]; injectConfig.clazz = parameterTypes[parameterIndex];
} }
if (this.injectMap.has(propertyKey)) { if (this.injectMap.has(propertyKey)) {
@ -73,7 +79,7 @@ class InjectDefinition {
} else { } else {
injectItem = { injectItem = {
stereotype: InjectSterotype.INJECT, stereotype: InjectSterotype.INJECT,
decoratorType: CoreConstants.DecoratorType.PARAMETER, decoratorType: DecoratorType.PARAMETER,
}; };
this.injectMap.set(propertyKey, injectItem); this.injectMap.set(propertyKey, injectItem);
} }
@ -90,20 +96,20 @@ class InjectDefinition {
} }
private addInjectProperty(injectConfig: InjectConfig, propertyKey: string | symbol): void { private addInjectProperty(injectConfig: InjectConfig, propertyKey: PropertyType): void {
if (this.injectMap.has(propertyKey)) { if (this.injectMap.has(propertyKey)) {
throw new Error(`Cannot apply @inject decorator on one property[${propertyKey}] multiple times.`); throw new Error(`Cannot apply @inject decorator on one property[${propertyKey}] multiple times.`);
} }
let propertyType: any = Reflect.getMetadata(CoreConstants.DESIGN_TYPE, this.target, propertyKey); let propertyType: any = Reflect.getMetadata(DESIGN_TYPE, this.clazz, propertyKey);
if (undefined === injectConfig.type) { if (undefined === injectConfig.clazz) {
injectConfig.type = propertyType; injectConfig.clazz = propertyType;
} }
let injectItem: InjectItem = { let injectItem: InjectItem = {
stereotype: InjectSterotype.INJECT, stereotype: InjectSterotype.INJECT,
decoratorType: CoreConstants.DecoratorType.PROPERTY, decoratorType: DecoratorType.PROPERTY,
propertyConfig: injectConfig, propertyConfig: injectConfig,
}; };

View File

@ -1,8 +1,23 @@
import { Construtorable } from '@loafer/core/constants'; import {
ClassType,
PropertyType,
} from '@loafer/core/constants';
interface PouchFactory { interface PouchFactory {
getPouch<T>(type: Construtorable<T>, ...args: any[]): T; /**
getPouchByQualifier<T>(type: Construtorable<T>, qualifier: string | symbol, ...args: any[]): T; * @param qualifier is identity of pouch
* @param clazz is type of pouch (if clazz is not specified, set the undefined)
* @param args are argument of target constructor
* @returns an instance of pouch
*/
getPouch(qualifier: PropertyType, clazz: ClassType, ...args: any[]): any;
/**
* @param clazz is type of pouch
* @param qualifier is identity of pouch (if qualifier is not specified, set the undefined)
* @param args are argument of target constructor
* @returns an instance of pouch
*/
getPouchByType(clazz: ClassType, qualifier: PropertyType, ...args: any[]): any;
} }

View File

@ -1,10 +1,11 @@
import { ClassType, PropertyType } from '@loafer/core/constants';
import { InjectableSterotype, PouchScope } from '@loafer/pouches/constants'; import { InjectableSterotype, PouchScope } from '@loafer/pouches/constants';
interface PouchDefinition { interface PouchDefinition {
readonly Type: Object; readonly Clazz: ClassType;
Stereotype: InjectableSterotype; Stereotype: InjectableSterotype;
Scope: PouchScope; Scope: PouchScope;
Qualifier: string | symbol; Qualifier: PropertyType;
readonly PostConstruct: Set<string>; readonly PostConstruct: Set<string>;
readonly PreDestroy: Set<string>; readonly PreDestroy: Set<string>;
addPostConstruct(postConstruct: string): void; addPostConstruct(postConstruct: string): void;

View File

@ -1,11 +1,14 @@
import { import {
Construtorable, ClassType,
PropertyType,
} from '@loafer/core/constants'; } from '@loafer/core/constants';
interface SingletonPouchRegistry { interface SingletonPouchRegistry {
registerSingleton(pouch: any, qualifier?: string | symbol): void; registerSingleton(pouch: any, qualifier?: PropertyType): void;
getSingleton<T>(type: Construtorable<T>, qualifier?: string | symbol): T; getSingleton(qualifier: PropertyType, clazz?: ClassType): any;
hasSingleton<T>(type: Construtorable<T>, qualifier?: string | symbol): boolean; getSingletonByClass(clazz: ClassType, qualifier?: PropertyType): any;
hasSingleton(qualifier: PropertyType, clazz?: ClassType): boolean;
hasSingletonByClass(clazz: ClassType, qualifier?: PropertyType): boolean;
} }
export default SingletonPouchRegistry; export default SingletonPouchRegistry;

View File

@ -1,3 +1,8 @@
import {
ClassType,
PropertyType,
} from '@loafer/core/constants';
import { import {
validateQualifier, validateQualifier,
} from '@loafer/pouches/util/qualifier'; } from '@loafer/pouches/util/qualifier';
@ -9,46 +14,46 @@ import DefaultSingletonPouchRegistry from '@loafer/pouches/factory/implement/Def
abstract class AbstractPouchFactory extends DefaultSingletonPouchRegistry implements PouchDefinitionRegistry { abstract class AbstractPouchFactory extends DefaultSingletonPouchRegistry implements PouchDefinitionRegistry {
protected pouchDefinitionMap: Map<string | symbol, Map<Object, PouchDefinition>>; protected pouchDefinitionMap: Map<PropertyType, Map<ClassType, PouchDefinition>>;
public constructor() { public constructor() {
super(); super();
this.pouchDefinitionMap = new Map(); this.pouchDefinitionMap = new Map();
} }
public registerPouchDefinition(pouchDefinition: PouchDefinition): void { public registerPouchDefinition(pouchDefinition: PouchDefinition): void {
let type = pouchDefinition.Type; let clazz = pouchDefinition.Clazz;
let qualifier = validateQualifier(type, pouchDefinition.Qualifier); let qualifier = validateQualifier(clazz, pouchDefinition.Qualifier);
if (this.hasPouchDefinition(type, qualifier)) { if (this.hasPouchDefinition(clazz, qualifier)) {
throw new Error(`Pouch Definition[${type.constructor.name}:${qualifier}] is exist already`); throw new Error(`Pouch Definition[${clazz.constructor.name}:${qualifier}] is exist already`);
} }
let map = this.pouchDefinitionMap.get(qualifier); let map = this.pouchDefinitionMap.get(qualifier);
if (undefined === map) { if (undefined === map) {
map = new Map(); map = new Map();
this.pouchDefinitionMap.set(qualifier, map); this.pouchDefinitionMap.set(qualifier, map);
} }
map.set(type, pouchDefinition); map.set(clazz, pouchDefinition);
} }
public removePouchDefinition(type: Object, qualifier?: string | symbol): void { public removePouchDefinition(clazz: ClassType, qualifier?: PropertyType): void {
const _qualifier = validateQualifier(type, qualifier); const _qualifier = validateQualifier(clazz, qualifier);
if (!this.hasPouchDefinition(type, _qualifier)) { if (!this.hasPouchDefinition(clazz, _qualifier)) {
throw new Error(`Pouch Definition[${type.constructor.name}:${qualifier}] is not exist`); throw new Error(`Pouch Definition[${clazz.constructor.name}:${qualifier}] is not exist`);
} }
this.pouchDefinitionMap.get(_qualifier).delete(type); this.pouchDefinitionMap.get(_qualifier).delete(clazz);
if (0 === this.pouchDefinitionMap.get(_qualifier).size) { if (0 === this.pouchDefinitionMap.get(_qualifier).size) {
this.pouchDefinitionMap.delete(_qualifier); this.pouchDefinitionMap.delete(_qualifier);
} }
} }
public getPouchDefinition(type: Object, qualifier?: string | symbol): PouchDefinition { public getPouchDefinition(clazz: ClassType, qualifier?: PropertyType): PouchDefinition {
const _qualifier = validateQualifier(type, qualifier); const _qualifier = validateQualifier(clazz, qualifier);
if (!this.pouchDefinitionMap.has(_qualifier)) { if (!this.pouchDefinitionMap.has(_qualifier)) {
return undefined; return undefined;
} }
return this.pouchDefinitionMap.get(_qualifier).get(type); return this.pouchDefinitionMap.get(_qualifier).get(clazz);
} }
public hasPouchDefinition(type: Object, qualifier?: string | symbol): boolean { public hasPouchDefinition(clazz: ClassType, qualifier?: PropertyType): boolean {
return undefined === this.getPouchDefinition(type, qualifier) ? false : true; return undefined === this.getPouchDefinition(clazz, qualifier) ? false : true;
} }

View File

@ -1,6 +1,7 @@
import { import {
Construtorable, ClassType,
DecoratorType, DecoratorType,
PropertyType,
} from '@loafer/core/constants'; } from '@loafer/core/constants';
import { import {
@ -19,19 +20,16 @@ class DefaultPouchFactory extends AbstractPouchFactory implements PouchFactory,
public constructor() { public constructor() {
super(); super();
} }
public getPouch(qualifier: PropertyType, clazz: ClassType, ...args: any[]): any {
public getPouch<T>(type: Construtorable<T>, ...args: any[]): T { return null;
let qualifier = validateQualifier(type.prototype, undefined);
return this.getPouchByQualifier(type, qualifier, args);
} }
public getPouchByType(clazz: ClassType, qualifier: PropertyType, ...args: any[]): any {
let _qualifier = validateQualifier(clazz, qualifier);
public getPouchByQualifier<T>(type: Construtorable<T>, qualifier: string | symbol, ...args: any[]): T { return null;
let clazz: Function = type.prototype;
let instance: T;
return instance;
} }
} }
export default DefaultPouchFactory; export default DefaultPouchFactory;

View File

@ -1,5 +1,6 @@
import { import {
Construtorable, ClassType,
PropertyType,
} from '@loafer/core/constants'; } from '@loafer/core/constants';
import SingletonPouchRegistry from '@loafer/pouches/factory/config/SingletonPouchRegistry'; import SingletonPouchRegistry from '@loafer/pouches/factory/config/SingletonPouchRegistry';
@ -9,44 +10,71 @@ import {
} from '@loafer/pouches/util/qualifier'; } from '@loafer/pouches/util/qualifier';
class DefaultSingletonPouchRegistry implements SingletonPouchRegistry { class DefaultSingletonPouchRegistry implements SingletonPouchRegistry {
protected singletonInstanceMap: Map<string | symbol, Map<Object, any>>; protected singletonInstanceMap: Map<PropertyType, Map<ClassType, any>>;
protected constructor() { protected constructor() {
} }
public registerSingleton(pouch: any, qualifier?: string | symbol): void { public registerSingleton(pouch: any, qualifier?: PropertyType): void {
let type: Object = Object.getPrototypeOf(pouch); let clazz: ClassType = Object.getPrototypeOf(pouch);
const _qualifier = validateQualifier(type, qualifier); const _qualifier = validateQualifier(clazz, qualifier);
if (this._hasSingleton(type, _qualifier)) { if (this._hasSingleton(_qualifier, clazz)) {
throw new Error(`Pouch Definition[${type.constructor.name}:${qualifier}] is exist already`); throw new Error(`Pouch Definition[${clazz.constructor.name}:${qualifier}] is exist already`);
} }
let map = this.singletonInstanceMap.get(_qualifier); let map = this.singletonInstanceMap.get(_qualifier);
if (undefined === map) { if (undefined === map) {
map = new Map(); map = new Map();
this.singletonInstanceMap.set(_qualifier, map); this.singletonInstanceMap.set(_qualifier, map);
} }
map.set(type, pouch); map.set(clazz, pouch);
}
public getSingleton<T>(target: Construtorable<T>, qualifier?: string | symbol): T {
let type = target.prototype;
return this._getSingleton(type, qualifier);
}
public hasSingleton<T>(target: Construtorable<T>, qualifier?: string | symbol): boolean {
return this._hasSingleton(target.prototype, qualifier);
} }
private _getSingleton<T>(type: Object, qualifier?: string | symbol): T { public getSingleton(qualifier: PropertyType, clazz?: ClassType): any {
const _qualifier = validateQualifier(type, qualifier); return this._getSingleton(qualifier, clazz);
}
public getSingletonByClass(clazz: ClassType, qualifier?: PropertyType): any {
const _qualifier = validateQualifier(clazz, qualifier);
return this._getSingleton(_qualifier, clazz);
}
public hasSingleton(qualifier: PropertyType, clazz?: ClassType): boolean {
return this._hasSingleton(qualifier, clazz);
}
public hasSingletonByClass(clazz: ClassType, qualifier?: PropertyType): boolean {
const _qualifier = validateQualifier(clazz, qualifier);
return this._hasSingleton(_qualifier, clazz);
}
if (!this.singletonInstanceMap.has(_qualifier)) {
private _getSingleton<T>(qualifier: PropertyType, clazz?: ClassType): T {
if (!this.singletonInstanceMap.has(qualifier)) {
return undefined; return undefined;
} }
return this.singletonInstanceMap.get(_qualifier).get(type); let map = this.singletonInstanceMap.get(qualifier);
let instance;
try {
instance = this._getInstance(map, clazz);
} catch(e) {
throw new Error(`Type of Pouch[${qualifier}] cannot be specified(count is ${map.size}).`);
}
return instance;
} }
private _hasSingleton(type: Object, qualifier?: string | symbol): boolean { private _hasSingleton(qualifier: PropertyType, clazz?: ClassType): boolean {
return undefined === this._getSingleton(type, qualifier) ? false : true; return undefined === this._getSingleton(qualifier, clazz) ? false : true;
}
private _getInstance(map: Map<ClassType, any>, clazz?: ClassType): any {
if (undefined !== clazz) {
return map.get(clazz);
}
const count = map.size;
if (1 < count) {
throw new Error(`Type of Pouch cannot be specified(count is ${count}).`);
}
for (let value of Array.from(map.values())) {
return value;
}
} }
} }

View File

@ -1,11 +1,15 @@
import { Construtorable } from '@loafer/core/constants'; import {
ClassType,
PropertyType,
} from '@loafer/core/constants';
import PouchDefinition from '@loafer/pouches/factory/config/PouchDefinition'; import PouchDefinition from '@loafer/pouches/factory/config/PouchDefinition';
interface PouchDefinitionRegistry { interface PouchDefinitionRegistry {
registerPouchDefinition(pouchDefinition: PouchDefinition): void; registerPouchDefinition(pouchDefinition: PouchDefinition): void;
removePouchDefinition(type: Object, qualifier?: string | symbol): void; removePouchDefinition(clazz: ClassType, qualifier?: PropertyType): void;
getPouchDefinition(type: Object, qualifier?: string | symbol): PouchDefinition; getPouchDefinition(clazz: ClassType, qualifier?: PropertyType): PouchDefinition;
hasPouchDefinition(type: Object, qualifier?: string | symbol): boolean; hasPouchDefinition(clazz: ClassType, qualifier?: PropertyType): boolean;
} }
export default PouchDefinitionRegistry; export default PouchDefinitionRegistry;

View File

@ -1,8 +1,9 @@
import { ClassType } from '@loafer/core/constants';
import getClassMetadata from '@loafer/core/util/metadata/getClassMetadata'; import getClassMetadata from '@loafer/core/util/metadata/getClassMetadata';
import { POUCH_INJECT_DEFINITION } from '@loafer/pouches/constants'; import { POUCH_INJECT_DEFINITION } from '@loafer/pouches/constants';
import InjectDefinition from '@loafer/pouches/definition/InjectDefinition'; import InjectDefinition from '@loafer/pouches/definition/InjectDefinition';
export const getInjectDefinition = export const getInjectDefinition =
(target: Object, isCreate: boolean = false) => (clazz: ClassType, isCreate: boolean = false) =>
getClassMetadata(target, POUCH_INJECT_DEFINITION, InjectDefinition, isCreate); getClassMetadata(clazz, POUCH_INJECT_DEFINITION, InjectDefinition, isCreate);

View File

@ -1,3 +1,8 @@
export const validateQualifier = (type: Object, qualifier: string | symbol) => { import {
return undefined === qualifier ? type.constructor.name : qualifier; ClassType,
PropertyType,
} from '@loafer/core/constants';
export const validateQualifier = (clazz: ClassType, qualifier: PropertyType) => {
return undefined === qualifier ? clazz.constructor.name : qualifier;
}; };