This commit is contained in:
crusader 2018-01-03 21:29:42 +09:00
parent 606d7b0e82
commit 61fb53a49c
28 changed files with 352 additions and 249 deletions

View File

@ -12,45 +12,69 @@ import {
RunnerAnnotation, RunnerAnnotation,
WebApplicationAnnotation, WebApplicationAnnotation,
} from './decorators'; } from './decorators';
import { InstanceDefinition } from '@overflow/commons/di/factory';
export class Application { export class Application {
private _primaryClass: ClassType; private _appClass: Class;
private _appAnnotation: WebApplicationAnnotation;
private _applicationContext: ApplicationContext; private _applicationContext: ApplicationContext;
public static async run(primaryClass: ClassType): Promise<ApplicationContext> { public constructor(primaryClass: ClassType) {
let app: Application = new Application(primaryClass); this.initialize(primaryClass);
return app.run();
} }
public constructor(primaryClass: ClassType) { private initialize(primaryClass: ClassType): void {
this._primaryClass = primaryClass; let clazz: Class = Class.forClassType(primaryClass);
this.createContext(); let wa: WebApplicationAnnotation = clazz.getOwnAnnotation(WebApplicationAnnotation);
if (undefined === wa) {
throw new Error(`Class is not WebApplication type. add @WebApplication annotation to class[${primaryClass.name}]`);
}
this._appClass = clazz;
this._appAnnotation = wa;
}
public static async run(primaryClass: ClassType): Promise<ApplicationContext> {
return new Application(primaryClass).run();
} }
/** /**
* run * run
*/ */
public run(): ApplicationContext { public run(): ApplicationContext {
this._applicationContext = new ApplicationContext();
let injectables: ClassType[] = this.getInjectables();
this._applicationContext.instanceDefinitionReader.registerInjectables(...injectables);
let runner = this.findRunner(); let runner = this.findRunner();
if (undefined === runner) { if (undefined === runner) {
throw new Error(`There is not exist @Runner on Application[${this._primaryClass.name}]`); throw new Error(`There is not exist @Runner on Application[${this._appClass.getName()}]`);
} }
let instanceFactory = this._applicationContext.instanceFactory; let instanceFactory = this._applicationContext.instanceFactory;
let clazz: Class = Class.forClassType(this._primaryClass); let instance = instanceFactory.getInstance();
let instance = clazz.getConstructor().newInstance();
instanceFactory.applyInstance(this._primaryClass, instance);
runner.invoke(instance); runner.invoke(instance);
return this._applicationContext; return this._applicationContext;
} }
private getInjectables(): ClassType[] {
let injectables: Set<ClassType> = new Set();
injectables.add(this._appClass.getType());
this._appAnnotation.attributes.injectables.forEach(injectableType => {
injectables.add(injectableType);
});
this._appAnnotation.attributes.configurations.forEach(configurationType => {
injectables.add(configurationType);
});
return Array.from(injectables);
}
private findRunner(): Method | undefined { private findRunner(): Method | undefined {
let clazz: Class = Class.forClassType(this._primaryClass); let methods = this._appClass.getOwnMethods();
let methods = clazz.getOwnMethods();
for (let key of Array.from(methods.keys())) { for (let key of Array.from(methods.keys())) {
let method = methods.get(key); let method = methods.get(key);
@ -64,59 +88,58 @@ export class Application {
return undefined; return undefined;
} }
private createContext(): ApplicationContext { // private createContext(): ApplicationContext {
let clazz: Class = Class.forClassType(this._primaryClass); // let clazz: Class = Class.forClassType(this._primaryClass);
let ans = TypeUtil.ancestorsOf(this._primaryClass);
let wa: WebApplicationAnnotation = clazz.getOwnAnnotation(WebApplicationAnnotation); // let wa: WebApplicationAnnotation = clazz.getOwnAnnotation(WebApplicationAnnotation);
if (undefined === wa) { // if (undefined === wa) {
throw new Error(`Class is not WebApplication type. add @WebApplication annotation to class[${this._primaryClass.name}]`); // throw new Error(`Class is not WebApplication type. add @WebApplication annotation to class[${this._primaryClass.name}]`);
} // }
this._applicationContext = new ApplicationContext(wa.attributes.injectables); // this._applicationContext = new ApplicationContext(wa.attributes.injectables);
this.registerJSONSources(wa.attributes.jsonSources); // this.registerJSONSources(wa.attributes.jsonSources);
this.registerConfigurations(wa.attributes.configurations); // this.registerConfigurations(wa.attributes.configurations);
return this._applicationContext; // return this._applicationContext;
} // }
private registerJSONSources(jsonSources: any[]): void { // private registerJSONSources(jsonSources: any[]): void {
if (undefined === jsonSources || null === jsonSources) { // if (undefined === jsonSources || null === jsonSources) {
return; // return;
} // }
let instanceFactory = this._applicationContext.instanceFactory; // let instanceFactory = this._applicationContext.instanceFactory;
let jsons = Object.assign({}, ...jsonSources); // let jsons = Object.assign({}, ...jsonSources);
instanceFactory.registerJSON(jsons); // instanceFactory.registerJSON(jsons);
} // }
private registerConfigurations(configurationTypes: ClassType[]): void { // private registerConfigurations(configurationTypes: ClassType[]): void {
if (undefined === configurationTypes || null === configurationTypes) { // if (undefined === configurationTypes || null === configurationTypes) {
return; // return;
} // }
let instanceFactory = this._applicationContext.instanceFactory; // let instanceFactory = this._applicationContext.instanceFactory;
configurationTypes.forEach(configurationType => { // configurationTypes.forEach(configurationType => {
let clazz: Class = Class.forClassType(configurationType); // let clazz: Class = Class.forClassType(configurationType);
let configAnnotation: ConfigurationAnnotation = clazz.getOwnAnnotation(ConfigurationAnnotation); // let configAnnotation: ConfigurationAnnotation = clazz.getOwnAnnotation(ConfigurationAnnotation);
if (undefined === configAnnotation) { // if (undefined === configAnnotation) {
throw new Error(`Class is not Configuration type. add @Configuration annotation to class[${configurationType.name}]`); // throw new Error(`Class is not Configuration type. add @Configuration annotation to class[${configurationType.name}]`);
} // }
let methods = clazz.getOwnMethods(); // let methods = clazz.getOwnMethods();
if (null === methods) { // if (null === methods) {
return; // return;
} // }
let instance = clazz.getConstructor().newInstance(); // let instance = clazz.getConstructor().newInstance();
instanceFactory.applyInstance(configurationType, instance); // instanceFactory.applyInstance(configurationType, instance);
methods.forEach(method => { // methods.forEach(method => {
let instanceAnnotation = method.getOwnAnnotation(InstanceAnnotation); // let instanceAnnotation = method.getOwnAnnotation(InstanceAnnotation);
if (undefined === instanceAnnotation) { // if (undefined === instanceAnnotation) {
return; // return;
} // }
let singletonName = null === instanceAnnotation.attributes.name ? method.getName() : instanceAnnotation.attributes.name; // let singletonName = null === instanceAnnotation.attributes.name ? method.getName() : instanceAnnotation.attributes.name;
let result = method.invoke(instance); // let result = method.invoke(instance);
instanceFactory.registerSingleton(singletonName, method.getReturnType(), result); // instanceFactory.registerSingleton(singletonName, method.getReturnType(), result);
}); // });
}); // });
} // }
} }

View File

@ -1,46 +0,0 @@
import {
ClassType,
} from '@overflow/commons/core/type';
import {
Class,
} from '@overflow/commons/core/reflect';
import {
InstanceDefinition,
InstanceFactory,
} from '@overflow/commons/di/factory';
import { InstanceDefinitionReader } from './instance_definition_reader';
export class ApplicationContext {
private _instanceFactory: InstanceFactory;
private _instanceDefinitionReader: InstanceDefinitionReader;
public constructor(injectables: ClassType[]) {
this._instanceFactory = new InstanceFactory();
this._instanceDefinitionReader = new InstanceDefinitionReader();
this.initializeInjectables(injectables);
}
private initializeInjectables(injectables: ClassType[]): void {
if (undefined === injectables) {
return;
}
injectables.forEach(injectable => {
let name = injectable.name;
let definition: InstanceDefinition = new InstanceDefinition(injectable);
this._instanceFactory.registerInstanceDefinition(name, definition);
});
}
/**
* instanceFactory
*/
public get instanceFactory(): InstanceFactory {
return this._instanceFactory;
}
}

View File

@ -1,3 +1,7 @@
import {
ClassType,
} from '@overflow/commons/core/type';
import { import {
InstanceFactory, InstanceFactory,
} from '@overflow/commons/di/factory'; } from '@overflow/commons/di/factory';
@ -10,66 +14,52 @@ import { InstanceDefinitionReader } from './instance_definition_reader';
export class ApplicationContext { export class ApplicationContext {
public static readonly MESSAGE_SOURCE_INSTANCE_NAME: string = 'messageSource'; public static readonly MESSAGE_SOURCE_INSTANCE_NAME: string = 'messageSource';
private readonly instanceFactoryPostProcessors: InstanceFactoryPostProcessor[] = []; private _id: ApplicationContextIDType;
private _parent: ApplicationContext;
private id: ApplicationContextIDType; private _messageSource: MessageSource;
private parent: ApplicationContext; private _instanceFactory: InstanceFactory;
private messageSource: MessageSource; private _instanceDefinitionReader: InstanceDefinitionReader;
private instanceFactory: InstanceFactory;
private instanceDefinitionReader: InstanceDefinitionReader;
public constructor(parent?: ApplicationContext) { public constructor(parent?: ApplicationContext) {
this.setParent(parent); this.parent = parent;
this._instanceFactory = new InstanceFactory();
this._instanceDefinitionReader = new InstanceDefinitionReader(this._instanceFactory.instanceDefinitionRegistry);
} }
// Context // Context
public getID(): ApplicationContextIDType { public get id(): ApplicationContextIDType {
return this.id; return this.id;
} }
public setID(id: ApplicationContextIDType): void { public set id(id: ApplicationContextIDType) {
this.id = id; this.id = id;
} }
public getApplicationName(): string { public get applicationName(): string {
return undefined; return undefined;
} }
public getParent(): ApplicationContext { public get parent(): ApplicationContext {
return this.parent; return this._parent;
} }
public setParent(parent: ApplicationContext): void { public set parent(parent: ApplicationContext) {
this.parent = parent; this._parent = parent;
} }
public getInstanceFactory(): InstanceFactory { public get instanceFactory(): InstanceFactory {
return undefined; return this._instanceFactory;
}
public get instanceDefinitionReader(): InstanceDefinitionReader {
return this._instanceDefinitionReader;
} }
// Configuration // Configuration
public addInstanceFactoryPostProcessor(instanceFactoryPostProcessor: InstanceFactoryPostProcessor): void {
this.instanceFactoryPostProcessors.push(instanceFactoryPostProcessor);
}
public getInstanceFactoryPostProcessor(): InstanceFactoryPostProcessor[] {
return this.instanceFactoryPostProcessors;
}
public addApplicationListener(listener: ApplicationListener): void {
//
}
public registerShutdownHook(): void {
//
}
public initMessageSource(): void {
//
}
// MessageSource // MessageSource
public getMessageSource(): MessageSource { public get messageSource(): MessageSource {
return this.messageSource; return this._messageSource;
} }
// Lifecycle // Lifecycle

View File

@ -1,2 +1,4 @@
export * from './application_context'; export * from './application_context';
export * from './instance_definition_reader'; export * from './instance_definition_reader';
export * from './scope_metadata';
export * from './scope_metadata_resolver';

View File

@ -2,30 +2,63 @@ import {
ClassType, ClassType,
} from '@overflow/commons/core/type'; } from '@overflow/commons/core/type';
import { Assert } from '@overflow/commons/core/util'; import { Annotation } from '@overflow/commons/core/reflect';
import {
Assert,
AnnotationUtils,
} from '@overflow/commons/core/util';
import { import {
InstanceDefinitionRegistry, InstanceNameGenerator,
InstanceDefinition, InstanceDefinition,
InstanceDefinitionRegistry,
InstanceNameGenerator,
} from '@overflow/commons/di/factory'; } from '@overflow/commons/di/factory';
import {
InstanceNameType,
NotInjectableError,
} from '@overflow/commons/di/type';
import { ScopeMetadataResolver } from './scope_metadata_resolver';
import { InjectableAnnotation, QualifierAnnotation } from '@overflow/commons/di/decorators';
export class InstanceDefinitionReader { export class InstanceDefinitionReader {
private instanceDefinitionRegistry: InstanceDefinitionRegistry; private instanceDefinitionRegistry: InstanceDefinitionRegistry;
private instanceNameGenerator: InstanceNameGenerator; private instanceNameGenerator: InstanceNameGenerator = new InstanceNameGenerator();
private scopeMetadataResolver: ScopeMetadataResolver = new ScopeMetadataResolver();
public constructor(registry: InstanceDefinitionRegistry) { public constructor(registry: InstanceDefinitionRegistry) {
Assert.notNull(registry, 'InstanceDefinitionRegistry must not be null'); Assert.notNull(registry, 'InstanceDefinitionRegistry must not be null');
this.instanceDefinitionRegistry = registry; this.instanceDefinitionRegistry = registry;
} }
public register(...injectables: ClassType[]): void { public registerInjectables(...injectables: ClassType[]): void {
injectables.forEach(injectable => { injectables.forEach(injectable => {
this.registerInstance(injectable); this.registerInjectable(injectable, undefined);
}); });
} }
public registerInstance(injectable: ClassType): void { public registerInjectable(injectable: ClassType, name: InstanceNameType | undefined, ...qualifiers: QualifierAnnotation[]): void {
let instanceDefinition: InstanceDefinition = new InstanceDefinition(injectable); if (!AnnotationUtils.hasAnnotation(injectable, InjectableAnnotation)) {
throw new NotInjectableError();
}
let definition: InstanceDefinition = new InstanceDefinition(injectable);
let scopeMeta = this.scopeMetadataResolver.resolveScopeMetadata(definition);
definition.scope = scopeMeta.scope;
let instanceName =
undefined !== name
? name
: this.instanceNameGenerator.generateInstanceName(definition, this.instanceDefinitionRegistry);
if (undefined !== qualifiers) {
qualifiers.forEach(qualifier => {
definition.addQualifier(qualifier);
});
}
this.instanceDefinitionRegistry.registerInstanceDefinition(instanceName, definition);
} }
} }

View File

@ -0,0 +1,13 @@
import { ScopeType } from '@overflow/commons/di/type';
export class ScopeMetadata {
private _scope: ScopeType = ScopeType.Singleton;
public get scope(): ScopeType {
return this._scope;
}
public set scope(scope: ScopeType) {
this._scope = scope;
}
}

View File

@ -9,12 +9,14 @@ import {
import { ScopeAnnotation } from '@overflow/commons/di/decorators'; import { ScopeAnnotation } from '@overflow/commons/di/decorators';
import { InstanceDefinition } from '@overflow/commons/di/factory'; import { InstanceDefinition } from '@overflow/commons/di/factory';
import { ScopeType } from '@overflow/commons/di/type'; import { ScopeType } from '@overflow/commons/di/type';
import { ScopeMetadata } from './scope_metadata';
export class ScopeMetadataResolver { export class ScopeMetadataResolver {
protected static scopeAnnotationType: ClassType<Annotation> = ScopeAnnotation; protected static scopeAnnotationType: ClassType<Annotation> = ScopeAnnotation;
public resolveScopeMetadata(definition: InstanceDefinition): ScopeType { public resolveScopeMetadata(definition: InstanceDefinition): ScopeMetadata {
let scopeMetadata: ScopeMetadata = new ScopeMetadata();
let scope: ScopeType = ScopeType.Default; let scope: ScopeType = ScopeType.Default;
} }

View File

@ -14,13 +14,15 @@ import {
export interface InstanceAnnotationAttributes { export interface InstanceAnnotationAttributes {
name?: InstanceNameType; name?: InstanceNameType;
initMethod?: Function;
destroyMethod?: Function;
} }
export class InstanceAnnotation extends Annotation { export class InstanceAnnotation extends Annotation {
public readonly attributes: InstanceAnnotationAttributes = { public readonly attributes: InstanceAnnotationAttributes = {
}; };
public constructor(name: InstanceNameType | InstanceNameType[] | InstanceAnnotationAttributes) { public constructor(name: InstanceNameType | InstanceAnnotationAttributes) {
super(); super();
if (undefined === name) { if (undefined === name) {
return; return;

View File

@ -8,12 +8,15 @@ import {
PropertyKeyType, PropertyKeyType,
} from '@overflow/commons/core/type'; } from '@overflow/commons/core/type';
import { Configuration } from './configuration';
export interface WebApplicationAnnotationAttributes { export interface WebApplicationAnnotationAttributes {
jsonSources?: any[]; jsonSources?: any[];
injectables?: ClassType[]; injectables?: ClassType[];
configurations?: ClassType[]; configurations?: ClassType[];
} }
@Configuration()
export class WebApplicationAnnotation extends Annotation { export class WebApplicationAnnotation extends Annotation {
public readonly attributes: WebApplicationAnnotationAttributes = { public readonly attributes: WebApplicationAnnotationAttributes = {
}; };

View File

@ -0,0 +1,36 @@
import { Class, Annotation } from '@overflow/commons/core/reflect';
import { ClassType } from '@overflow/commons/core/type';
export abstract class AnnotationUtils {
public static hasAnnotation<T extends Annotation>(classType: ClassType, annotationClass: ClassType<T>): boolean {
let annotation = AnnotationUtils.getAnnotation(classType, annotationClass);
if (undefined !== annotation) {
return true;
}
return false;
}
public static getAnnotation<T extends Annotation>(classType: ClassType, annotationClass: ClassType<T>): T | undefined {
let clazz = Class.forClassType(classType);
if (undefined === clazz) {
return undefined;
}
let annotations = clazz.getAnnotations();
if (0 === annotations.size) {
return undefined;
}
for (const annonClassType of Array.from(annotations.keys())) {
if (annonClassType === annotationClass) {
return <T>annotations.get(annonClassType);
}
let annotation = AnnotationUtils.getAnnotation(annonClassType, annotationClass);
if (undefined !== annotation) {
return annotation;
}
}
return undefined;
}
}

View File

@ -1,5 +1,5 @@
import { IllegalArgumentError } from '../type/error'; import { IllegalArgumentError } from '../type/error';
import { StringUtil, StringUtils } from './string'; import { StringUtils } from './string';

View File

@ -1,3 +1,4 @@
export * from './annotation';
export * from './assert'; export * from './assert';
export * from './locale'; export * from './locale';
export * from './registry'; export * from './registry';

View File

@ -1,6 +1,5 @@
export * from './inject'; export * from './inject';
export * from './injectable'; export * from './injectable';
export * from './named';
export * from './post_construct'; export * from './post_construct';
export * from './pre_destroy'; export * from './pre_destroy';
export * from './qualifier'; export * from './qualifier';

View File

@ -13,25 +13,25 @@ import {
} from '@overflow/commons/di/type'; } from '@overflow/commons/di/type';
export interface InjectAnnotationAttributes { export interface InjectAnnotationAttributes {
name?: InstanceNameType; required?: boolean;
} }
export class InjectAnnotation extends Annotation { export class InjectAnnotation extends Annotation {
public readonly attributes: InjectAnnotationAttributes = { public readonly attributes: InjectAnnotationAttributes = {
required: true,
}; };
public constructor(name: InstanceNameType | InjectAnnotationAttributes) { public constructor(required?: boolean | InjectAnnotationAttributes) {
super(); super();
if (undefined === name) { if (undefined === required) {
return; return;
} }
if (TypeUtil.isString(name)) { if (TypeUtil.isBoolean(required)) {
this.attributes.name = <InstanceNameType>name; this.attributes.required = <boolean>required;
} else { } else {
this.copyAttributes(this.attributes, <InjectAnnotationAttributes>name); this.copyAttributes(this.attributes, <InjectAnnotationAttributes>required);
} }
} }

View File

@ -13,24 +13,22 @@ import {
} from '@overflow/commons/di/type'; } from '@overflow/commons/di/type';
export interface InjectableAnnotationAttributes { export interface InjectableAnnotationAttributes {
name?: InstanceNameType[]; name?: InstanceNameType;
} }
export class InjectableAnnotation extends Annotation { export class InjectableAnnotation extends Annotation {
public readonly attributes: InjectableAnnotationAttributes = { public readonly attributes: InjectableAnnotationAttributes = {
name: undefined,
}; };
public constructor(name: InstanceNameType | InstanceNameType[] | InjectableAnnotationAttributes) { public constructor(name?: InstanceNameType | InjectableAnnotationAttributes) {
super(); super();
if (undefined === name) { if (undefined === name) {
return; return;
} }
if (TypeUtil.isString(name)) { if (TypeUtil.isString(name)) {
this.attributes.name = [<InstanceNameType>name]; this.attributes.name = <InstanceNameType>name;
} else if (TypeUtil.isArray(name)) {
this.attributes.name = <InstanceNameType[]>name;
} else { } else {
this.copyAttributes(this.attributes, <InjectableAnnotationAttributes>name); this.copyAttributes(this.attributes, <InjectableAnnotationAttributes>name);
} }
@ -40,11 +38,6 @@ export class InjectableAnnotation extends Annotation {
console.log('Injectable'); console.log('Injectable');
} }
public methodDecorator<T>(target: Object, propertyKey: PropertyKeyType,
descriptor: TypedPropertyDescriptor<T>): TypedPropertyDescriptor<T> | void {
console.log('Injectable');
}
} }
export const Injectable = Decorator.create(InjectableAnnotation); export const Injectable = Decorator.create(InjectableAnnotation);

View File

@ -9,25 +9,14 @@ import {
} from '@overflow/commons/core/type'; } from '@overflow/commons/core/type';
export interface PostConstructAnnotationAttributes { export interface PostConstructAnnotationAttributes {
name?: string[];
} }
export class PostConstructAnnotation extends Annotation { export class PostConstructAnnotation extends Annotation {
public readonly attributes: PostConstructAnnotationAttributes = { public readonly attributes: PostConstructAnnotationAttributes = {
}; };
public constructor(name: string | string[] | PostConstructAnnotationAttributes) { public constructor() {
super(); super();
if (undefined === name) {
return;
}
if (TypeUtil.isString(name)) {
this.attributes.name = [<string>name];
} else {
this.copyAttributes(this.attributes, <PostConstructAnnotationAttributes>name);
}
} }
public methodDecorator<T>(target: Object, propertyKey: PropertyKeyType, public methodDecorator<T>(target: Object, propertyKey: PropertyKeyType,

View File

@ -9,7 +9,6 @@ import {
} from '@overflow/commons/core/type'; } from '@overflow/commons/core/type';
export interface PreDestroyAnnotationAttributes { export interface PreDestroyAnnotationAttributes {
name?: string[];
} }
export class PreDestroyAnnotation extends Annotation { export class PreDestroyAnnotation extends Annotation {
@ -17,17 +16,8 @@ export class PreDestroyAnnotation extends Annotation {
}; };
public constructor(name: string | string[] | PreDestroyAnnotationAttributes) { public constructor() {
super(); super();
if (undefined === name) {
return;
}
if (TypeUtil.isString(name)) {
this.attributes.name = [<string>name];
} else {
this.copyAttributes(this.attributes, <PreDestroyAnnotationAttributes>name);
}
} }
public methodDecorator<T>(target: Object, propertyKey: PropertyKeyType, public methodDecorator<T>(target: Object, propertyKey: PropertyKeyType,

View File

@ -0,0 +1,55 @@
import {
Annotation,
Decorator,
} from '@overflow/commons/core/reflect';
import {
PropertyKeyType,
TypeUtil,
} from '@overflow/commons/core/type';
import {
InstanceNameType,
} from '@overflow/commons/di/type';
export interface QualifierAnnotationAttributes {
name?: InstanceNameType;
}
export class QualifierAnnotation extends Annotation {
public readonly attributes: QualifierAnnotationAttributes = {
name: '',
};
public constructor(name: InstanceNameType | QualifierAnnotationAttributes) {
super();
if (undefined === name) {
return;
}
if (TypeUtil.isString(name)) {
this.attributes.name = <InstanceNameType>name;
} else {
this.copyAttributes(this.attributes, <QualifierAnnotationAttributes>name);
}
}
public classDecorator<TFunction extends Function>(target: TFunction): TFunction | void {
console.log('Qualifier');
}
public propertyDecorator(target: Object, propertyKey: PropertyKeyType): void {
console.log('Qualifier');
}
public methodDecorator<T>(target: Object, propertyKey: PropertyKeyType,
descriptor: TypedPropertyDescriptor<T>): TypedPropertyDescriptor<T> | void {
console.log('Qualifier');
}
public parameterDecorator(target: Object, propertyKey: PropertyKeyType, parameterIndex: number): void {
console.log('Qualifier');
}
}
export const Qualifier = Decorator.create(QualifierAnnotation);

View File

@ -46,10 +46,6 @@ export class ResourceAnnotation extends Annotation {
descriptor: TypedPropertyDescriptor<T>): TypedPropertyDescriptor<T> | void { descriptor: TypedPropertyDescriptor<T>): TypedPropertyDescriptor<T> | void {
console.log('Resource'); console.log('Resource');
} }
public parameterDecorator(target: Object, propertyKey: PropertyKeyType, parameterIndex: number): void {
console.log('Resource');
}
} }
export const Resource = Decorator.create(ResourceAnnotation); export const Resource = Decorator.create(ResourceAnnotation);

View File

@ -14,21 +14,21 @@ import {
} from '@overflow/commons/di/type'; } from '@overflow/commons/di/type';
export interface ScopeAnnotationAttributes { export interface ScopeAnnotationAttributes {
value?: ScopeType; scope?: ScopeType;
} }
export class ScopeAnnotation extends Annotation { export class ScopeAnnotation extends Annotation {
public readonly attributes: ScopeAnnotationAttributes = { public readonly attributes: ScopeAnnotationAttributes = {
value: ScopeType.Default, scope: ScopeType.Default,
}; };
public constructor(value: ScopeType | ScopeAnnotationAttributes) { public constructor(scope: ScopeType | ScopeAnnotationAttributes) {
super(); super();
if (undefined !== (<ScopeAnnotationAttributes>value).value) { if (undefined !== (<ScopeAnnotationAttributes>scope).scope) {
this.copyAttributes(this.attributes, <ScopeAnnotationAttributes>value); this.copyAttributes(this.attributes, <ScopeAnnotationAttributes>scope);
} else { } else {
this.attributes.value = value; this.attributes.scope = <ScopeType>scope;
} }
} }

View File

@ -34,6 +34,11 @@ export class ValueAnnotation extends Annotation {
console.log('Value'); console.log('Value');
} }
public methodDecorator<T>(target: Object, propertyKey: PropertyKeyType,
descriptor: TypedPropertyDescriptor<T>): TypedPropertyDescriptor<T> | void {
console.log('Value');
}
public parameterDecorator(target: Object, propertyKey: PropertyKeyType, parameterIndex: number): void { public parameterDecorator(target: Object, propertyKey: PropertyKeyType, parameterIndex: number): void {
console.log('Value'); console.log('Value');
} }

View File

@ -2,3 +2,4 @@ export * from './instance_definition_registry';
export * from './instance_definition'; export * from './instance_definition';
export * from './instance_factory'; export * from './instance_factory';
export * from './instance_name_generator'; export * from './instance_name_generator';
export * from './singleton_instance_registry';

View File

@ -1,39 +1,41 @@
import {
Class,
} from '@overflow/commons/core/reflect';
import {
ClassType,
} from '@overflow/commons/core/type';
import { Assert } from '@overflow/commons/core/util'; import { Assert } from '@overflow/commons/core/util';
import { ScopeType, InjectModeType } from '@overflow/commons/di/type';
import {
QualifierAnnotation,
} from '@overflow/commons/di/decorators';
import {
ScopeType,
InjectModeType,
NotInjectableError,
} from '@overflow/commons/di/type';
export class InstanceDefinition { export class InstanceDefinition {
private readonly attributes: Map<string, any> = new Map(); private readonly attributes: Map<string, any> = new Map();
private scope: ScopeType = ScopeType.Default; private _instanceClass: Class;
private injectMode: InjectModeType = InjectModeType.No; private _scope: ScopeType = ScopeType.Default;
private _injectMode: InjectModeType = InjectModeType.No;
// Attributes
public setAttribute(name: string, value?: any): void { public constructor(instanceClassType: ClassType) {
Assert.notNull(name, 'Name must not be null'); let clazz = Class.forClassType(instanceClassType);
if (value !== undefined) { if (undefined === clazz) {
this.attributes.set(name, value); throw new NotInjectableError();
} else {
this.removeAttribute(name);
} }
this._instanceClass = clazz;
} }
public getAttribute(name: string): any | undefined { public get instanceClass(): Class {
Assert.notNull(name, 'Name must not be null'); return this._instanceClass;
return this.attributes.get(name);
}
public removeAttribute(name: string): boolean {
Assert.notNull(name, 'Name must not be null');
return this.attributes.delete(name);
}
public hasAttribute(name: string): boolean {
Assert.notNull(name, 'Name must not be null');
return this.attributes.has(name);
}
public attributeNames(): IterableIterator<string> {
return this.attributes.keys();
} }
// Metadata // Metadata
@ -41,14 +43,22 @@ export class InstanceDefinition {
return undefined; return undefined;
} }
public setScope(scope: ScopeType): void { public set scope(scope: ScopeType) {
this.scope = scope; this.scope = scope;
} }
public getScope(): ScopeType { public get scope(): ScopeType {
return this.scope; return this.scope;
} }
public get injectMode(): InjectModeType {
return this._injectMode;
}
public set injectMode(injectMode: InjectModeType) {
this._injectMode = injectMode;
}
public isSingleton(): boolean { public isSingleton(): boolean {
return ScopeType.Singleton === this.scope || ScopeType.Default === this.scope; return ScopeType.Singleton === this.scope || ScopeType.Default === this.scope;
} }
@ -57,12 +67,7 @@ export class InstanceDefinition {
return ScopeType.Transiant === this.scope; return ScopeType.Transiant === this.scope;
} }
public setInjectMode(injectMode: InjectModeType): void { public addQualifier(qualifier: QualifierAnnotation): void {
this.injectMode = injectMode; //
} }
public getInjectMode(): InjectModeType {
return this.injectMode;
}
} }

View File

@ -7,7 +7,7 @@ import {
} from '@overflow/commons/core/type'; } from '@overflow/commons/core/type';
import { import {
InjectType, InjectModeType,
InstanceNameType, InstanceNameType,
} from '@overflow/commons/di/type'; } from '@overflow/commons/di/type';
@ -15,9 +15,13 @@ import { InstanceDefinition } from './instance_definition';
import { InstanceDefinitionRegistry } from './instance_definition_registry'; import { InstanceDefinitionRegistry } from './instance_definition_registry';
export class InstanceFactory { export class InstanceFactory {
private instanceDefinitionRegistry: InstanceDefinitionRegistry; private _instanceDefinitionRegistry: InstanceDefinitionRegistry;
public get instanceDefinitionRegistry(): InstanceDefinitionRegistry {
return this._instanceDefinitionRegistry;
}
// Instance // Instance
public getInstance(name: InstanceNameType | undefined, requiredType: ClassType | undefined, ...args: any[]): any | undefined { public getInstance(name: InstanceNameType | undefined, requiredType: ClassType | undefined, ...args: any[]): any | undefined {
@ -44,7 +48,7 @@ export class InstanceFactory {
// Create Instance // Create Instance
public createInstance<T>(clazzType: ClassType<T>, injectMode?: InjectType, dependencyCheck?: boolean): T { public createInstance<T>(clazzType: ClassType<T>, injectMode?: InjectModeType, dependencyCheck?: boolean): T {
return undefined; return undefined;
} }
@ -52,11 +56,11 @@ export class InstanceFactory {
// //
} }
public inject(clazzType: ClassType, injectMode?: InjectType, dependencyCheck?: boolean): any { public inject(clazzType: ClassType, injectMode?: InjectModeType, dependencyCheck?: boolean): any {
// //
} }
public injectInstanceProperties(instance: any, injectMode: InjectType, dependencyCheck: boolean): void { public injectInstanceProperties(instance: any, injectMode: InjectModeType, dependencyCheck: boolean): void {
// //
} }

View File

@ -5,6 +5,13 @@ export class InstanceError extends Error {
} }
} }
export class NotInjectableError extends InstanceError {
public constructor(message?: string) {
super(message);
Object.setPrototypeOf(this, new.target.prototype);
}
}
export class NoSuchInstanceDefinitionError extends InstanceError { export class NoSuchInstanceDefinitionError extends InstanceError {
public constructor(message?: string) { public constructor(message?: string) {
super(message); super(message);