This commit is contained in:
crusader 2017-12-29 16:15:10 +09:00
parent b3189213e5
commit 046ea0e6f2
8 changed files with 129 additions and 56 deletions

View File

@ -2,7 +2,7 @@ import {
Class,
Method,
} from '@overflow/commons/core/reflect';
import { ClassType } from '@overflow/commons/core/type';
import { ClassType, PropertyKeyType } from '@overflow/commons/core/type';
import { ApplicationContext } from './context';
import {
ConfigurationAnnotation,
@ -32,36 +32,34 @@ export class Application {
*/
public async run(): Promise<ApplicationContext> {
let runner = this.findRunner();
if (null === runner) {
if (undefined === runner) {
throw new Error(`There is not exist @Runner on Application[${this._primaryClass.name}]`);
}
let instanceFactory = this._applicationContext.instanceFactory;
let instance = instanceFactory.getInstance(null, this._primaryClass);
let clazz: Class = Class.forClass(this._primaryClass);
let instance = clazz.getConstructor().newInstance();
instanceFactory.applyInstance(this._primaryClass, instance);
await runner.invoke(instance);
return this._applicationContext;
}
private findRunner(): Method {
private findRunner(): Method | undefined {
let clazz: Class = Class.forClass(this._primaryClass);
let methods = clazz.getOwnMethods();
if (null === methods || 0 === methods.size) {
return null;
}
for (const key in methods.keys()) {
if (methods.hasOwnProperty(key)) {
const method = methods[key];
for (let key of Array.from(methods.keys())) {
let method = methods.get(key);
let runnerAnnotation = method.getOwnAnnotation(RunnerAnnotation);
if (undefined === runnerAnnotation) {
continue;
}
return method;
}
}
return null;
return undefined;
}
private createContext(): ApplicationContext {
@ -105,7 +103,8 @@ export class Application {
if (null === methods) {
return;
}
let instance = instanceFactory.getInstance(null, configurationType);
let instance = clazz.getConstructor().newInstance();
instanceFactory.applyInstance(configurationType, instance);
methods.forEach(method => {
let instanceAnnotation = method.getOwnAnnotation(InstanceAnnotation);
if (undefined === instanceAnnotation) {

View File

@ -52,7 +52,6 @@ export class Class extends AccessibleObject {
this._clazzType = clazzType;
this._fields = new Map();
this._methods = new Map();
this._constructor = null;
}
/**
@ -96,6 +95,9 @@ export class Class extends AccessibleObject {
}
public getConstructor(): Constructor {
if (undefined === this._constructor) {
this._constructor = new Constructor(this, undefined);
}
return this._constructor;
}

View File

@ -9,7 +9,7 @@ import {Executable} from './executable';
export class Constructor extends Executable {
private _rawConstructor: Function;
public constructor(declaringClazz: Class, parameterTypes: any[]) {
public constructor(declaringClazz: Class, parameterTypes?: any[]) {
super(declaringClazz, CONSTRUCTOR_NAME, parameterTypes);
this._rawConstructor = TypeUtil.getPrototype(declaringClazz.getType())[CONSTRUCTOR_NAME];
}

View File

@ -13,13 +13,13 @@ export abstract class Executable extends AccessibleObject implements Member {
private _name: PropertyKeyType;
private _parameters: Parameter[];
protected constructor(declaringClazz: Class, name: PropertyKeyType, parameterTypes: any[]) {
protected constructor(declaringClazz: Class, name: PropertyKeyType, parameterTypes?: any[]) {
super();
this._clazz = declaringClazz;
this._name = name;
if (null === parameterTypes) {
if (undefined === parameterTypes) {
return;
}

View File

@ -13,7 +13,7 @@ import {
} from '@overflow/commons/di/type';
export interface InjectAnnotationAttributes {
name?: InstanceNameType[];
name?: InstanceNameType;
}
export class InjectAnnotation implements Annotation {
@ -29,11 +29,7 @@ export class InjectAnnotation implements Annotation {
if (TypeUtil.isString(name)) {
this.attributes = {
name: [<InstanceNameType>name],
};
} else if (TypeUtil.isArray(name)) {
this.attributes = {
name: <InstanceNameType[]>name,
name: <InstanceNameType>name,
};
} else {
this.attributes = <InjectAnnotationAttributes>name;

View File

@ -13,7 +13,7 @@ import {
} from '@overflow/commons/di/type';
export interface ResourceAnnotationAttributes {
name: InstanceNameType[];
name?: InstanceNameType;
}
export class ResourceAnnotation implements Annotation {
@ -22,12 +22,14 @@ export class ResourceAnnotation implements Annotation {
public constructor(name: InstanceNameType | ResourceAnnotationAttributes) {
if (undefined === name) {
throw new Error(`name attribute must be specified.`);
this.attributes = {
};
return;
}
if (TypeUtil.isString(name)) {
this.attributes = {
name: [<InstanceNameType>name],
name: <InstanceNameType>name,
};
} else {
this.attributes = <ResourceAnnotationAttributes>name;

View File

@ -1,27 +1,35 @@
import {
ClassType,
ClassType, PropertyKeyType,
} from '@overflow/commons/core/type';
import {
Class, Annotation, Field,
} from '@overflow/commons/core/reflect';
import {
ValueAnnotation, InjectAnnotation, ResourceAnnotation,
} from '@overflow/commons/di/decorators';
import {
InstanceNameType,
InstanceFactoryType,
} from '@overflow/commons/di/type';
import {InstanceDefinitionRegistry} from './instance_definition_registry';
import {InstanceDefinition} from './instance_definition';
export class InstanceFactory implements InstanceDefinitionRegistry {
private singletonObjects: Map<InstanceNameType, any> = new Map();
private singletonFactories: Map<InstanceNameType, InstanceFactoryType> = new Map();
private instanceDefinitionMap: Map<InstanceNameType, InstanceDefinition> = new Map();
private instanceDefinitionNames: Set<InstanceNameType> = new Set();
private _singletonObjects: Map<InstanceNameType, any> = new Map();
private _singletonFactories: Map<InstanceNameType, InstanceFactoryType> = new Map();
private _instanceDefinitionMap: Map<InstanceNameType, InstanceDefinition> = new Map();
private _instanceDefinitionNames: Set<InstanceNameType> = new Set();
private _values: any;
/**
* getInstance
*/
public getInstance(name: InstanceNameType, requiredType: ClassType, ...args: any[]): any {
public getInstance(name: InstanceNameType, requiredType: ClassType, ...args: any[]): any | undefined {
if (null === name) {
return this.getInstanceByType(requiredType);
name = requiredType.name;
}
let sharedInstance = this.getSingleton(name);
@ -29,20 +37,74 @@ export class InstanceFactory implements InstanceDefinitionRegistry {
return sharedInstance;
}
return null;
let instanceDefinition = this.getInstanceDefinition(name);
let clazzType = instanceDefinition.instanceClass;
let clazz = Class.forClass(clazzType);
if (undefined === clazz) {
return undefined;
}
let ctor = clazz.getConstructor();
let ctorParams = ctor.getParameters();
let ctorArgs = [];
if (0 < ctorParams.length) {
//
}
private getInstanceByName(requiredType: ClassType): any {
let instance = ctor.newInstance(ctorArgs);
this.applyInstance(clazzType, instance);
return instance;
}
private getInstanceByType(requiredType: ClassType): any {
private getInstanceByName(requiredType: ClassType): any | undefined {
return undefined;
}
private getInstanceByType(requiredType: ClassType): any | undefined {
return undefined;
}
/**
* applyInstance
*/
public applyInstance(clazzType: ClassType, instance: any): void {
let clazz: Class = Class.forClass(clazzType);
let fields = clazz.getFields();
fields.forEach((field: Field, key: PropertyKeyType, map: Map<PropertyKeyType, Field>): void => {
let fieldAnnotations = field.getAnnotations();
fieldAnnotations.forEach((value: Annotation, annonType: ClassType, annonMap: Map<ClassType, Annotation>): void => {
switch (annonType) {
case ValueAnnotation:
{
let annon = <ValueAnnotation>value;
instance[field.getName()] = this.getValue(annon.attributes.value);
}
break;
case InjectAnnotation:
{
let annon = <InjectAnnotation>value;
instance[field.getName()] = this.getInstance(annon.attributes.name, field.getType());
}
break;
case ResourceAnnotation:
{
let annon = <ResourceAnnotation>value;
instance[field.getName()] = this.getSingleton(annon.attributes.name || field.getName());
}
break;
default:
break;
}
});
});
}
private getSingleton(name: InstanceNameType): any | undefined {
let singletonObject = this.singletonObjects.get(name);
let singletonObject = this._singletonObjects.get(name);
}
/**
@ -53,44 +115,56 @@ export class InstanceFactory implements InstanceDefinitionRegistry {
}
public registerJSON(json: any): void {
//
this._values = json;
}
/**
* getValue
*/
public getValue(keyPath: string): any {
let paths = keyPath.split('.');
let result = this._values;
for (let i = 0, len = paths.length; i < len; i++) {
result = result[paths[i]];
}
return result;
}
public registerSingleton(name: InstanceNameType, instanceType: any, instance: any): void {
//
this._singletonObjects.set(name, instance);
}
public registerInstanceDefinition(name: InstanceNameType, instanceDefinition: InstanceDefinition): void {
let oldInstanceDefinition = this.instanceDefinitionMap.get(name);
let oldInstanceDefinition = this._instanceDefinitionMap.get(name);
if (undefined !== oldInstanceDefinition) {
throw new Error(`InstanceDefinition[${name}] is already exist.`);
}
this.instanceDefinitionNames.add(name);
this.instanceDefinitionMap.set(name, instanceDefinition);
this._instanceDefinitionNames.add(name);
this._instanceDefinitionMap.set(name, instanceDefinition);
}
public removeInstanceDefinition(name: InstanceNameType): void {
if (!this.instanceDefinitionMap.has(name)) {
if (!this._instanceDefinitionMap.has(name)) {
throw new Error(`InstanceDefinition[${name}] is not exist.`);
}
this.instanceDefinitionNames.delete(name);
this.instanceDefinitionMap.delete(name);
this._instanceDefinitionNames.delete(name);
this._instanceDefinitionMap.delete(name);
}
public getInstanceDefinition(name: InstanceNameType): InstanceDefinition | undefined {
return this.instanceDefinitionMap.get(name);
return this._instanceDefinitionMap.get(name);
}
public containsInstanceDefinition(name: InstanceNameType): boolean {
return this.instanceDefinitionMap.has(name);
return this._instanceDefinitionMap.has(name);
}
public getInstanceDefinitionNames(): Set<InstanceNameType> {
return this.instanceDefinitionNames;
return this._instanceDefinitionNames;
}
public getInstanceDefinitionCount(): number {
return this.instanceDefinitionMap.size;
return this._instanceDefinitionMap.size;
}
public isInstanceNameInUse(name: InstanceNameType): boolean {

View File

@ -83,7 +83,7 @@ class WebAppApplication extends B {
private htmlContainerID: string;
private container: HTMLElement;
@Inject()
@Resource()
private store: Store<any>;
private history: History;