ing
This commit is contained in:
parent
f0247ea2bd
commit
8be774ec18
|
@ -32,6 +32,19 @@ export class Application {
|
|||
|
||||
this._appClass = clazz;
|
||||
this._appAnnotation = wa;
|
||||
|
||||
this._applicationContext = new ApplicationContext();
|
||||
|
||||
let injectables: ClassType[] = this._appAnnotation.attributes.injectables;
|
||||
this._applicationContext.registerInjectables(...injectables);
|
||||
|
||||
let configurations: ClassType[] = this._appAnnotation.attributes.configurations;
|
||||
this._applicationContext.registerConfigurations(...configurations);
|
||||
|
||||
let jsonSources: any[] = this._appAnnotation.attributes.jsonSources;
|
||||
this._applicationContext.registerJSONSources(...jsonSources);
|
||||
|
||||
this._applicationContext.registerInjectable(this._appClass.getType(), undefined);
|
||||
}
|
||||
|
||||
public static async run(primaryClass: ClassType): Promise<ApplicationContext> {
|
||||
|
@ -42,18 +55,13 @@ export class Application {
|
|||
* run
|
||||
*/
|
||||
public run(): ApplicationContext {
|
||||
this._applicationContext = new ApplicationContext();
|
||||
|
||||
let injectables: ClassType[] = this.getInjectables();
|
||||
this._applicationContext.instanceDefinitionReader.registerInjectables(...injectables);
|
||||
|
||||
let runner = this.findRunner();
|
||||
if (undefined === runner) {
|
||||
throw new Error(`There is not exist @Runner on Application[${this._appClass.getName()}]`);
|
||||
}
|
||||
let instanceFactory = this._applicationContext.instanceFactory;
|
||||
|
||||
let instance = instanceFactory.getInstance();
|
||||
let instance = this._applicationContext.getInstance(undefined, this._appClass.getType());
|
||||
|
||||
runner.invoke(instance);
|
||||
|
||||
|
|
|
@ -6,17 +6,20 @@ import {
|
|||
InstanceFactory,
|
||||
} from '@overflow/commons/di/factory';
|
||||
|
||||
import {
|
||||
InstanceNameType,
|
||||
} from '@overflow/commons/di/type';
|
||||
|
||||
import { ApplicationContextIDType } from '@overflow/commons/application/type';
|
||||
|
||||
import { MessageSource } from './message_source';
|
||||
import { JSONSource } from './json_source';
|
||||
import { InstanceDefinitionReader } from './instance_definition_reader';
|
||||
|
||||
export class ApplicationContext {
|
||||
public static readonly MESSAGE_SOURCE_INSTANCE_NAME: string = 'messageSource';
|
||||
|
||||
private _id: ApplicationContextIDType;
|
||||
private _parent: ApplicationContext;
|
||||
private _messageSource: MessageSource;
|
||||
private _jsonSource: JSONSource;
|
||||
private _instanceFactory: InstanceFactory;
|
||||
private _instanceDefinitionReader: InstanceDefinitionReader;
|
||||
|
||||
|
@ -24,9 +27,9 @@ export class ApplicationContext {
|
|||
this.parent = parent;
|
||||
this._instanceFactory = new InstanceFactory();
|
||||
this._instanceDefinitionReader = new InstanceDefinitionReader(this._instanceFactory.instanceDefinitionRegistry);
|
||||
this._jsonSource = new JSONSource();
|
||||
}
|
||||
|
||||
|
||||
// Context
|
||||
|
||||
public get id(): ApplicationContextIDType {
|
||||
|
@ -47,19 +50,11 @@ export class ApplicationContext {
|
|||
this._parent = parent;
|
||||
}
|
||||
|
||||
public get instanceFactory(): InstanceFactory {
|
||||
return this._instanceFactory;
|
||||
}
|
||||
|
||||
public get instanceDefinitionReader(): InstanceDefinitionReader {
|
||||
return this._instanceDefinitionReader;
|
||||
}
|
||||
|
||||
// Configuration
|
||||
|
||||
// MessageSource
|
||||
public get messageSource(): MessageSource {
|
||||
return this._messageSource;
|
||||
// JSONSource
|
||||
public get jsonSource(): JSONSource {
|
||||
return this._jsonSource;
|
||||
}
|
||||
|
||||
// Lifecycle
|
||||
|
@ -73,4 +68,22 @@ export class ApplicationContext {
|
|||
public isRunning(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Instance
|
||||
public registerInjectables(...injectables: ClassType[]): void {
|
||||
this._instanceDefinitionReader.registerInjectables(...injectables);
|
||||
}
|
||||
|
||||
public registerInjectable(injectable: ClassType, name: InstanceNameType | undefined): InstanceNameType {
|
||||
return this._instanceDefinitionReader.registerInjectable(injectable, name);
|
||||
}
|
||||
|
||||
public registerConfigurations(...configurations: ClassType[]): void {
|
||||
return this._instanceDefinitionReader.registerConfigurations(...configurations);
|
||||
}
|
||||
|
||||
public registerJSONSources(...jsonSources: any[]): void {
|
||||
this._jsonSource.addSources(...jsonSources);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
export * from './application_context';
|
||||
export * from './instance_definition_reader';
|
||||
export * from './json_source';
|
||||
export * from './scope_metadata';
|
||||
export * from './scope_metadata_resolver';
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
import {
|
||||
Annotation,
|
||||
Class,
|
||||
Method,
|
||||
} from '@overflow/commons/core/reflect';
|
||||
|
||||
import {
|
||||
ClassType,
|
||||
PropertyKeyType,
|
||||
NotDecoratedClassError,
|
||||
} from '@overflow/commons/core/type';
|
||||
|
||||
import { Annotation } from '@overflow/commons/core/reflect';
|
||||
|
||||
import {
|
||||
Assert,
|
||||
AnnotationUtils,
|
||||
|
@ -25,6 +31,15 @@ import {
|
|||
NotInjectableError,
|
||||
} from '@overflow/commons/di/type';
|
||||
|
||||
import {
|
||||
ConfigurationAnnotation,
|
||||
InstanceAnnotation,
|
||||
} from '@overflow/commons/application/decorators';
|
||||
|
||||
import {
|
||||
NotConfigurationError,
|
||||
} from '@overflow/commons/application/type';
|
||||
|
||||
import { ScopeMetadataResolver } from './scope_metadata_resolver';
|
||||
|
||||
export class InstanceDefinitionReader {
|
||||
|
@ -43,13 +58,18 @@ export class InstanceDefinitionReader {
|
|||
});
|
||||
}
|
||||
|
||||
public registerInjectable<QT extends Annotation>
|
||||
(injectable: ClassType, name: InstanceNameType | undefined, ...qualifierTypes: ClassType<QT>[]): void {
|
||||
public registerInjectable(injectable: ClassType, name: InstanceNameType | undefined): InstanceNameType {
|
||||
let clazz = Class.forClassType(injectable);
|
||||
if (undefined === clazz) {
|
||||
throw new NotDecoratedClassError();
|
||||
}
|
||||
|
||||
if (!AnnotationUtils.hasAnnotation(injectable, InjectableAnnotation)) {
|
||||
throw new NotInjectableError(`Class[${injectable.name}] does not contains @Injectable`);
|
||||
}
|
||||
|
||||
let definition: InstanceDefinition = new InstanceDefinition(injectable);
|
||||
let definition: InstanceDefinition = new InstanceDefinition();
|
||||
definition.instanceClass = clazz;
|
||||
let scopeMeta = this.scopeMetadataResolver.resolveScopeMetadata(definition);
|
||||
definition.scope = scopeMeta.scope;
|
||||
let instanceName =
|
||||
|
@ -57,12 +77,42 @@ export class InstanceDefinitionReader {
|
|||
? name
|
||||
: this.instanceNameGenerator.generateInstanceName(definition, this.instanceDefinitionRegistry);
|
||||
|
||||
if (undefined !== qualifiers) {
|
||||
qualifiers.forEach(qualifier => {
|
||||
definition.addQualifier(qualifier);
|
||||
});
|
||||
this.instanceDefinitionRegistry.registerInstanceDefinition(instanceName, definition);
|
||||
|
||||
return instanceName;
|
||||
}
|
||||
|
||||
public registerConfigurations(...configurations: ClassType[]): void {
|
||||
configurations.forEach(configuration => {
|
||||
this.registerConfiguration(configuration);
|
||||
});
|
||||
}
|
||||
|
||||
public registerConfiguration(configuration: ClassType): void {
|
||||
let clazz = Class.forClassType(configuration);
|
||||
if (undefined === clazz) {
|
||||
throw new NotDecoratedClassError();
|
||||
}
|
||||
|
||||
this.instanceDefinitionRegistry.registerInstanceDefinition(instanceName, definition);
|
||||
if (!AnnotationUtils.hasAnnotation(configuration, ConfigurationAnnotation)) {
|
||||
throw new NotConfigurationError(`Class[${configuration.name}] does not contains @Configuration`);
|
||||
}
|
||||
|
||||
let factoryInstanceName = this.registerInjectable(configuration, undefined);
|
||||
let methods = clazz.getMethods();
|
||||
|
||||
methods.forEach((method: Method, methodName: PropertyKeyType) => {
|
||||
let ia = method.getAnnotation(InstanceAnnotation);
|
||||
if (undefined === ia) {
|
||||
return;
|
||||
}
|
||||
let instanceName = undefined !== ia.attributes.name ? ia.attributes.name : method.getName();
|
||||
|
||||
let definition: InstanceDefinition = new InstanceDefinition();
|
||||
definition.factoryInstanceName = factoryInstanceName;
|
||||
definition.factoryMethod = method;
|
||||
|
||||
this.instanceDefinitionRegistry.registerInstanceDefinition(instanceName, definition);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
21
src/ts/@overflow/commons/application/context/json_source.ts
Normal file
21
src/ts/@overflow/commons/application/context/json_source.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { Locale } from '@overflow/commons/core/util';
|
||||
|
||||
export class JSONSource {
|
||||
private _jsonSources: any;
|
||||
|
||||
public constructor() {
|
||||
this._jsonSources = {};
|
||||
}
|
||||
|
||||
public addSources(...jsonSources: any[]): void {
|
||||
if (undefined === jsonSources || null === jsonSources) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._jsonSources = Object.assign(this._jsonSources, ...jsonSources);
|
||||
}
|
||||
|
||||
public getSource(code: string, args: any[], defaultMessage: string | undefined, locale: Locale): string {
|
||||
return undefined;
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
import { Locale } from '@overflow/commons/core/util';
|
||||
|
||||
export class MessageSource {
|
||||
public getMessage(code: string, args: any[], defaultMessage: string | undefined, locale: Locale): string {
|
||||
return undefined;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
export * from './configuration';
|
||||
export * from './instance';
|
||||
export * from './json_source';
|
||||
export * from './runner';
|
||||
export * from './web_application';
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import {
|
||||
Annotation,
|
||||
Decorator,
|
||||
} from '@overflow/commons/core/reflect';
|
||||
|
||||
import {
|
||||
PropertyKeyType,
|
||||
TypeUtil,
|
||||
} from '@overflow/commons/core/type';
|
||||
|
||||
export interface JSONSourceAnnotationAttributes {
|
||||
key: string;
|
||||
}
|
||||
|
||||
export class JSONSourceAnnotation extends Annotation {
|
||||
public readonly attributes: JSONSourceAnnotationAttributes = {
|
||||
key: undefined,
|
||||
};
|
||||
|
||||
public constructor(key: string | JSONSourceAnnotationAttributes) {
|
||||
super();
|
||||
if (undefined === key) {
|
||||
throw new Error(`key attribute must be specified.`);
|
||||
}
|
||||
|
||||
if (TypeUtil.isString(key)) {
|
||||
this.attributes.key = <string>key;
|
||||
} else {
|
||||
this.copyAttributes(this.attributes, <JSONSourceAnnotationAttributes>key);
|
||||
}
|
||||
}
|
||||
|
||||
public propertyDecorator(target: Object, propertyKey: PropertyKeyType): void {
|
||||
console.log('JSONSource');
|
||||
}
|
||||
|
||||
public parameterDecorator(target: Object, propertyKey: PropertyKeyType, parameterIndex: number): void {
|
||||
console.log('JSONSource');
|
||||
}
|
||||
}
|
||||
|
||||
export const JSONSource = Decorator.create(JSONSourceAnnotation);
|
|
@ -8,7 +8,9 @@ import {
|
|||
PropertyKeyType,
|
||||
} from '@overflow/commons/core/type';
|
||||
|
||||
import { Configuration } from './configuration';
|
||||
import {
|
||||
Injectable,
|
||||
} from '@overflow/commons/di/decorators';
|
||||
|
||||
export interface WebApplicationAnnotationAttributes {
|
||||
jsonSources?: any[];
|
||||
|
@ -16,7 +18,7 @@ export interface WebApplicationAnnotationAttributes {
|
|||
configurations?: ClassType[];
|
||||
}
|
||||
|
||||
@Configuration()
|
||||
@Injectable()
|
||||
export class WebApplicationAnnotation extends Annotation {
|
||||
public readonly attributes: WebApplicationAnnotationAttributes = {
|
||||
};
|
||||
|
|
13
src/ts/@overflow/commons/application/type/error.ts
Normal file
13
src/ts/@overflow/commons/application/type/error.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
export class ApplicationError extends Error {
|
||||
public constructor(message?: string) {
|
||||
super(message);
|
||||
Object.setPrototypeOf(this, new.target.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
export class NotConfigurationError extends ApplicationError {
|
||||
public constructor(message?: string) {
|
||||
super(message);
|
||||
Object.setPrototypeOf(this, new.target.prototype);
|
||||
}
|
||||
}
|
|
@ -1 +1,2 @@
|
|||
export * from './error';
|
||||
export * from './type';
|
||||
|
|
|
@ -12,4 +12,9 @@ export class NotSupportedDecoratorError extends Error {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
export class NotDecoratedClassError extends Error {
|
||||
public constructor(message?: string) {
|
||||
super(message);
|
||||
Object.setPrototypeOf(this, new.target.prototype);
|
||||
}
|
||||
}
|
||||
|
|
3
src/ts/@overflow/commons/di/factory/argument_values.ts
Normal file
3
src/ts/@overflow/commons/di/factory/argument_values.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export class ArgumentValues {
|
||||
|
||||
}
|
|
@ -1,9 +1,13 @@
|
|||
import {
|
||||
Annotation,
|
||||
Class,
|
||||
Method,
|
||||
Parameter,
|
||||
} from '@overflow/commons/core/reflect';
|
||||
|
||||
import {
|
||||
ClassType,
|
||||
PropertyKeyType,
|
||||
} from '@overflow/commons/core/type';
|
||||
|
||||
import { Assert } from '@overflow/commons/core/util';
|
||||
|
@ -15,34 +19,65 @@ import {
|
|||
import {
|
||||
ScopeType,
|
||||
InjectModeType,
|
||||
InstanceFactoryType,
|
||||
InstanceNameType,
|
||||
NotInjectableError,
|
||||
} from '@overflow/commons/di/type';
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Class: create by class constructor (class, constructor parameter)
|
||||
* Instance method: create by instance method (instance name, method name, method parameter)
|
||||
*/
|
||||
|
||||
export class InstanceDefinition {
|
||||
private readonly attributes: Map<string, any> = new Map();
|
||||
private _instanceClass: Class;
|
||||
private _factoryInstanceName: InstanceNameType;
|
||||
private _factoryMethod: Method;
|
||||
private _annotations: Map<ClassType, Annotation>;
|
||||
|
||||
private _scope: ScopeType = ScopeType.Default;
|
||||
private _injectMode: InjectModeType = InjectModeType.No;
|
||||
|
||||
public constructor() {
|
||||
this._annotations = new Map();
|
||||
}
|
||||
|
||||
public constructor(instanceClassType: ClassType) {
|
||||
let clazz = Class.forClassType(instanceClassType);
|
||||
if (undefined === clazz) {
|
||||
throw new NotInjectableError();
|
||||
}
|
||||
public set instanceClass(instanceClass: Class) {
|
||||
this._instanceClass = instanceClass;
|
||||
|
||||
this._instanceClass = clazz;
|
||||
let annotations = instanceClass.getOwnAnnotations();
|
||||
annotations.forEach((annon: Annotation, classType: ClassType) => {
|
||||
this._annotations.set(classType, annon);
|
||||
});
|
||||
}
|
||||
|
||||
public get instanceClass(): Class {
|
||||
return this._instanceClass;
|
||||
}
|
||||
|
||||
// Metadata
|
||||
public getMetadata(): AnnotationMetadata {
|
||||
return undefined;
|
||||
public set factoryInstanceName(factoryInstanceName: InstanceNameType) {
|
||||
this._factoryInstanceName = factoryInstanceName;
|
||||
}
|
||||
|
||||
public get factoryInstanceName(): InstanceNameType {
|
||||
return this._factoryInstanceName;
|
||||
}
|
||||
|
||||
public set factoryMethod(factoryMethod: Method) {
|
||||
this._factoryMethod = factoryMethod;
|
||||
|
||||
let annotations = factoryMethod.getOwnAnnotations();
|
||||
annotations.forEach((annon: Annotation, classType: ClassType) => {
|
||||
this._annotations.set(classType, annon);
|
||||
});
|
||||
}
|
||||
|
||||
public get factoryMethod(): Method {
|
||||
return this._factoryMethod;
|
||||
}
|
||||
|
||||
// Metadata
|
||||
public set scope(scope: ScopeType) {
|
||||
this.scope = scope;
|
||||
}
|
||||
|
@ -51,14 +86,6 @@ export class InstanceDefinition {
|
|||
return this.scope;
|
||||
}
|
||||
|
||||
public get injectMode(): InjectModeType {
|
||||
return this._injectMode;
|
||||
}
|
||||
|
||||
public set injectMode(injectMode: InjectModeType) {
|
||||
this._injectMode = injectMode;
|
||||
}
|
||||
|
||||
public isSingleton(): boolean {
|
||||
return ScopeType.Singleton === this.scope || ScopeType.Default === this.scope;
|
||||
}
|
||||
|
|
|
@ -4,12 +4,26 @@ import {
|
|||
|
||||
import {InstanceDefinition} from './instance_definition';
|
||||
|
||||
export interface InstanceDefinitionRegistry {
|
||||
registerInstanceDefinition(name: InstanceNameType, instanceDefinition:InstanceDefinition): void;
|
||||
removeInstanceDefinition(name: InstanceNameType): void;
|
||||
getInstanceDefinition(name: InstanceNameType): InstanceDefinition;
|
||||
containsInstanceDefinition(name: InstanceNameType): boolean;
|
||||
getInstanceDefinitionNames(): Set<InstanceNameType>;
|
||||
getInstanceDefinitionCount(): number;
|
||||
isInstanceNameInUse(name: InstanceNameType): boolean;
|
||||
export class InstanceDefinitionRegistry {
|
||||
public registerInstanceDefinition(name: InstanceNameType, instanceDefinition:InstanceDefinition): void {
|
||||
//
|
||||
}
|
||||
public removeInstanceDefinition(name: InstanceNameType): void {
|
||||
//
|
||||
}
|
||||
public getInstanceDefinition(name: InstanceNameType): InstanceDefinition | undefined {
|
||||
return undefined;
|
||||
}
|
||||
public containsInstanceDefinition(name: InstanceNameType): boolean {
|
||||
return false;
|
||||
}
|
||||
public getInstanceDefinitionNames(): Set<InstanceNameType> | undefined {
|
||||
return undefined;
|
||||
}
|
||||
public getInstanceDefinitionCount(): number {
|
||||
return 0;
|
||||
}
|
||||
public isInstanceNameInUse(name: InstanceNameType): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,9 @@ import { InstanceDefinitionRegistry } from './instance_definition_registry';
|
|||
export class InstanceFactory {
|
||||
private _instanceDefinitionRegistry: InstanceDefinitionRegistry;
|
||||
|
||||
public constructor() {
|
||||
this._instanceDefinitionRegistry = new InstanceDefinitionRegistry();
|
||||
}
|
||||
|
||||
public get instanceDefinitionRegistry(): InstanceDefinitionRegistry {
|
||||
return this._instanceDefinitionRegistry;
|
||||
|
|
|
@ -59,14 +59,6 @@ declare global {
|
|||
const module: { hot: any };
|
||||
}
|
||||
|
||||
abstract class B {
|
||||
public abstract b(): void;
|
||||
}
|
||||
|
||||
// abstract class C {
|
||||
// public abstract c(): void;
|
||||
// }
|
||||
|
||||
@WebApplication({
|
||||
injectables: injectables,
|
||||
jsonSources: jsonSources,
|
||||
|
@ -77,18 +69,10 @@ abstract class B {
|
|||
WebAppConfiguration,
|
||||
],
|
||||
})
|
||||
class WebAppApplication implements B {
|
||||
class WebAppApplication {
|
||||
private static isProduction:boolean = process.env.NODE_ENV === 'production' ? true : false;
|
||||
private static useReduxDevTools:boolean = window.devToolsExtension && !WebAppApplication.isProduction ? true : false;
|
||||
|
||||
public b(): void {
|
||||
//
|
||||
}
|
||||
|
||||
public c(): void {
|
||||
//
|
||||
}
|
||||
|
||||
@Resource()
|
||||
private containerPromise: Promise<HTMLElement>;
|
||||
private container: HTMLElement;
|
||||
|
|
Loading…
Reference in New Issue
Block a user