@ts-ioc/core
v4.0.5
Published
tsioc is AOP, Ioc container, via typescript decorator
Downloads
345
Maintainers
Readme
packaged @ts-ioc/core
This repo is for distribution on npm
. The source for this module is in the
main repo.
@ts-ioc/core
is AOP, Ioc container, via typescript decorator.
version 2+ of tsioc
builder
build: npm run build
//build with version:
npm run build -- --setvs=4.0.0-beta
//deploy:
./deploy.cmd
//or
npm run build -- --deploy=true
Install
npm install @ts-ioc/core
// in browser
npm install @ts-ioc/platform-browser
// in server
npm install @ts-ioc/platform-server
add extends modules
use aop
// install aop
npm install @ts-ioc/aop
import { AopModule } from '@ts-ioc/aop';
// in server
import { ContainerBuilder } from '@ts-ioc/platform-server'
// in browser
import { ContainerBuilder } from '@ts-ioc/platform-browser'
let builder = new ContainerBuilder();
let container = build.create();
container.use(AopModule);
use aop logs
// install aop logs
npm install @ts-ioc/logs
import { LogModule } from '@ts-ioc/logs';
// in server
import { ContainerBuilder } from '@ts-ioc/platform-server'
// in browser
import { ContainerBuilder } from '@ts-ioc/platform-browser'
let builder = new ContainerBuilder();
let container = build.create();
container.use(LogModule);
Documentation
class name First char must be UpperCase.
Ioc
Register one class will auto register depdence class (must has a class decorator).
get Instance can auto create constructor param. (must has a class decorator or register in container).
Has decorators
@Abstract
abstract class decorator.@AutoRun
class, method decorator, use to define the class auto run (via a method or not) after registered.@AutoWried
property or param decorator, use to auto wried type instance or value to the instance of one class with the decorator.@Component
class decortator, use to define the class. it can setting provider to some token, singleton or not. it will executeComponentLifecycle
hooks when create a instance .@Inject
property or param decorator, use to auto wried type instance or value to the instance of one class with the decorator.@Injectable
class decortator, use to define the class. it can setting provider to some token, singleton or not.@IocExt
class decortator, use to define the class is Ioc extends module. it will auto run after registered to helper your to setup module.@Method
method decorator.@Param
param decorator, use to auto wried type instance or value to the instance of one class with the decorator.@Singleton
class decortator, use to define the class is singleton.@Providers
Providers decorator, for class. use to add private ref service for the class.@Refs
Refs decorator, for class. use to define the class as a service for target.
AOP
It's a dynamic aop base on ioc.
define a Aspect class, must with decorator:
@Aspect
Aspect decorator, define for class. use to define class as aspect. it can setting provider to some token, singleton or not.@Before(matchstring|RegExp)
method decorator, aop Before advice decorator.@After(matchstring|RegExp)
method decorator, aop after advice decorator.@Around(matchstring|RegExp)
method decorator, aop around advice decorator.@AfterThrowing(matchstring|RegExp)
method decorator, aop AfterThrowing advice decorator.@AfterReturning(matchstring|RegExp)
method decorator, aop AfterReturning advice decorator.@Pointcut(matchstring|RegExp)
method decorator, aop Pointcut advice decorator.
see simples
DIModule and boot
DI Module manager, application bootstrap. base on AOP.
@DIModule
DIModule decorator, use to define class as DI Module.@Annotation
Annotation decorator, use to define class build metadata config.
see activity build boot simple
import { DIModule, ApplicationBuilder } from '@ts-ioc/bootstrap';
export class TestService {
testFiled = 'test';
test() {
console.log('test');
}
}
@DIModule({
providers: [
{ provide: 'mark', useFactory: () => 'marked' },
TestService
],
exports: [
]
})
export class ModuleA {
}
@Injectable
export class ClassSevice {
@Inject('mark')
mark: string;
state: string;
start() {
console.log(this.mark);
}
}
@Aspect
export class Logger {
@Around('execution(*.start)')
log() {
console.log('start........');
}
}
@DIModule({
imports: [
AopModule,
Logger,
ModuleA
],
exports: [
ClassSevice
],
bootstrap: ClassSevice
})
export class ModuleB {
}
ApplicationBuilder.create(__dirname)
.bootstrap(ModuleB)
Activites
create Container
- in browser can not:
- use syncBuild
- syncLoadModule
- can not use minimatch to match file.
- support es5 uglify, @ts-ioc/annotations [] or typescript-class-annotations to get class annotations before typescript compile.
let builder = new ContainerBuilder();
// 1. via create.
let container = builder.create();
// 2. via build.
//with BuildOptions to auto register module.
let container = await builder.build({
files: [__dirname +'/controller/**/*.ts', __dirname + '/*.model.js'],
moudles:['node-modules-name', ClassType]
});
// 3. via syncBuild
let container = builder.syncBuild({
moudles:['node-modules-name', ClassType]
});
init & register Container
see interface IContainer
// 1. you can load modules by self
await builder.loadModule(container, {
files: [__dirname +'/controller/**/*.ts', __dirname + '/*.model.js'],
moudles:['node-modules-name', ClassType]
});
// 2. load sync
builder.syncLoadModule(container, {
moudles:['node-modules-name', ClassType]
});
// 3. use modules
container.use(...modules);
// 4. register a class
container.register(Person);
// 5. register a factory;
container.register(Person, (container)=> {
...
return new Person(...);
});
// 6. register with keyword
container.register('keyword', Perosn);
// 8. register with alais
container.register(new Registration(Person, aliasname));
get instance of type
// 8. get instance use get method of container.
/**
* resolve type instance with token and param provider.
*
* @template T
* @param {Token<T>} token
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IResolver
*/
resolve<T>(token: Token<T>, ...providers: ProviderTypes[]): T;
/**
* Retrieves an instance from the container based on the provided token.
*
* @template T
* @param {Token<T>} token
* @param {string} [alias]
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
get<T>(token: Token<T>, alias?: string, ...providers: ProviderTypes[]): T;
/**
* resolve token value in this container only.
*
* @template T
* @param {Token<T>} token
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
resolveValue<T>(token: Token<T>, ...providers: ProviderTypes[]): T;
/**
* get service or target reference service.
*
* @template T
* @param {Token<T>} token servive token.
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
getService<T>(token: Token<T>, ...providers: ProviderTypes[]): T;
/**
* get service or target reference service.
*
* @template T
* @param {Token<T>} token servive token.
* @param {(Token<any> | Token<any>[])} [target] service refrence target.
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
getService<T>(token: Token<T>, target: Token<any> | Token<any>[], ...providers: ProviderTypes[]): T;
/**
* get service or target reference service.
*
* @template T
* @param {Token<T>} token servive token.
* @param {(Token<any> | Token<any>[])} [target] service refrence target.
* @param {RefTokenFac<T>} toRefToken
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
getService<T>(token: Token<T>, target: Token<any> | Token<any>[], toRefToken: RefTokenFac<T>, ...providers: ProviderTypes[]): T;
/**
* get service or target reference service.
*
* @template T
* @param {Token<T>} token servive token.
* @param {(Token<any> | Token<any>[])} [target] service refrence target.
* @param {(boolean | Token<T>)} defaultToken
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
getService<T>(token: Token<T>, target: Token<any> | Token<any>[], defaultToken: boolean | Token<T>, ...providers: ProviderTypes[]): T;
/**
* get service or target reference service.
*
* @template T
* @param {Token<T>} token servive token.
* @param {(Token<any> | Token<any>[])} [target] service refrence target.
* @param {RefTokenFac<T>} toRefToken
* @param {(boolean | Token<T>)} defaultToken
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
getService<T>(token: Token<T>, target: Token<any> | Token<any>[], toRefToken: RefTokenFac<T>, defaultToken: boolean | Token<T>, ...providers: ProviderTypes[]): T;
/**
* get target reference service.
*
* @template T
* @param {ReferenceToken<T>} [refToken] reference service Registration Injector
* @param {(Token<any> | Token<any>[])} target the service reference to.
* @param {Token<T>} [defaultToken] default service token.
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
getRefService<T>(refToken: ReferenceToken<T>, target: Token<any> | Token<any>[], defaultToken?: Token<T>, ...providers: ProviderTypes[]): T
//get simple person
let person = container.get(Person);
//get colloge person
let person = container.get(Person, 'Colloge');
// resolve with providers
container.resolve(Person, ...providers);
Invoke method
you can use yourself MethodAccessor
by implement IMethodAccessor, register MethodAccessorToken
with your MethodAccessor
in container, see interface IMethodAccessor.
@Injectable
class Person {
constructor() {
}
say() {
return 'I love you.'
}
}
@Injectable
class Child extends Person {
constructor() {
super();
}
say() {
return 'Mama';
}
}
class MethodTest {
constructor() {
}
@Method
sayHello(person: Person) {
return person.say();
}
}
class MethodTest2 {
constructor() {
}
@Method()
sayHello( @Inject(Child) person: Person) {
return person.say();
}
}
class MethodTest3 {
constructor() {
}
@Method
sayHello( @Inject(Child) personA: Person, personB: Person) {
return personA.say() + ', ' + personB.say();
}
}
@Injectable
class Geet {
constructor(private name: string){
}
print(hi?:string){
return `${hi}, from ${this.name}`;
}
}
container.register(Geet);
container.invoke(Geet, 'print', null,
{hi: 'How are you.', name:'zhou' },
{ hi: (container: IContainer)=> 'How are you.' }, ... },
{ hi:{type: Token<any>, value: any |(container: IContainer)=>any }},
Provider.createParam('name', 'zhou'),
Provider.create('hi', value:'Hello'),
// or use ProviderMap.
...
)
container.resolve(Geet,
{name: 'zhou' },
{ name: (container: IContainer)=>any } },
{name:{type: Token<any>, value: any|(container: IContainer)=>any }})
container.register(MethodTest);
container.invoke(MethodTest, 'sayHello')
.then(data =>{
console.log(data);
});
container.register(MethodTest2);
container.invoke(MethodTest2, 'sayHello')
.then(data =>{
console.log(data);
});
container.register(MethodTest3);
container.invoke(MethodTest3, 'sayHello')
.then(data =>{
console.log(data);
});
Use Demo
import { Method, ContainerBuilder, AutoWired, Injectable, Singleton, IContainer, ParameterMetadata, Param, Aspect } from '@ts-ioc/core';
export class SimppleAutoWried {
constructor() {
}
@AutoWired
dateProperty: Date;
}
@Singleton
export class Person {
name = 'testor';
}
// > v0.3.5 all class decorator can depdence.
@Singleton
// @Injectable
export class RoomService {
constructor() {
}
@AutoWired
current: Date;
}
@Injectable()
export class ClassRoom {
constructor(public service: RoomService) {
}
}
export abstract class Student {
constructor() {
}
abstract sayHi(): string;
}
@Injectable({ provide: Student })
export class MiddleSchoolStudent extends Student {
constructor() {
super();
}
sayHi() {
return 'I am a middle school student';
}
}
@Injectable()
export class MClassRoom {
@AutoWired(MiddleSchoolStudent)
leader: Student;
constructor() {
}
}
@Injectable({ provide: Student, alias: 'college' })
export class CollegeStudent extends Student {
constructor() {
super();
}
sayHi() {
return 'I am a college student';
}
}
@Injectable
export class CollegeClassRoom {
constructor(
@Param(CollegeStudent)
@AutoWired(CollegeStudent)
public leader: Student) {
}
}
@Injectable
export class InjMClassRoom {
// @Inject(MiddleSchoolStudent)
@Inject
// @Inject({ type: MiddleSchoolStudent })
// @Inject({ provider: MiddleSchoolStudent })
leader: Student;
constructor() {
}
}
export interface IClassRoom {
leader: Student;
}
@Injectable
export class InjCollegeClassRoom {
constructor(
// all below decorator can work, also @AutoWired, @Param is.
// @Inject(new Registration(Student, 'college')) // need CollegeStudent also register.
@Inject(CollegeStudent)
// @Inject({ provider: CollegeStudent })
// @Inject({ provider: Student, alias: 'college' }) //need CollegeStudent also register.
// @Inject({ type: CollegeStudent })
public leader: Student
) {
}
}
@Injectable
export class InjCollegeAliasClassRoom {
constructor(
// all below decorator can work, also @AutoWired, @Param is.
@Inject(new Registration(Student, 'college')) // need CollegeStudent also register.
// @Inject(CollegeStudent)
// @Inject({ provider: CollegeStudent })
// @Inject({ provider: Student, alias: 'college' }) // need CollegeStudent also register.
// @Inject({ type: CollegeStudent })
public leader: Student
) {
}
}
@Injectable('StringClassRoom')
export class StingMClassRoom {
// @Inject(MiddleSchoolStudent)
@Inject
// @Inject({ type: MiddleSchoolStudent })
leader: Student;
constructor() {
}
}
export class StringIdTest {
constructor(@Inject('StringClassRoom') public room: IClassRoom) {
}
}
export const CollClassRoom = Symbol('CollegeClassRoom');
@Injectable(CollClassRoom)
export class SymbolCollegeClassRoom {
@Inject(CollegeStudent)
leader: Student;
constructor() {
}
}
export class SymbolIdest {
@Inject(CollClassRoom)
public room: IClassRoom
constructor() {
}
}
@Injectable
class MethodTestPerson {
say() {
return 'hello word.'
}
}
class MethodTest {
@Method
sayHello(person: MethodTestPerson) {
return person.say();
}
}
// 1. Custom register one class will auto inject depdence class (must has a class decorator).
let builder = new ContainerBuilder();
let container = builder.create();
container.register(MethodTest);
container.invoke(MethodTest, 'sayHello')
.then(data =>{
console.log(data);
});
container.register(SimppleAutoWried);
let instance = container.get(SimppleAutoWried);
console.log(instance.dateProperty);
container.register(ClassRoom);
let room = container.get(ClassRoom);
console.log(room.service.current);
container.register(MiddleSchoolStudent);
container.register(CollegeStudent);
let student = container.get(Student);
console.log(student.sayHi());
let student2 = container.get(new Registration(Student, 'college'));
console.log(student2.sayHi());
let student3 = container.get(Student, 'college'));
console.log(student3.sayHi());
builder.build({
files: __dirname + '/*{.ts,.js}'
})
.then(container => {
let instance = container.get(Student);
console.log(instance.sayHi());
let instance2 = container.get(new Registration(Student, 'college'));
console.log(instance2.sayHi());
let instance3 = container.get(Student, 'college');
console.log(instance3.sayHi())
});
Extend decorator
see interface LifeScope You can extend yourself decorator via:
createClassDecorator
/**
* create class decorator
*
* @export
* @template T metadata type.
* @param {string} name decorator name.
* @param {MetadataAdapter} [adapter] metadata adapter
* @param {MetadataExtends<T>} [metadataExtends] add extents for metadata.
* @returns {*}
*/
export function createClassDecorator<T extends ClassMetadata>(name: string, adapter?: MetadataAdapter, metadataExtends?: MetadataExtends<T>): IClassDecorator<T>
createClassMethodDecorator
/**
* create method decorator.
*
* @export
* @template T metadata type.
* @param {string} name decorator name.
* @param {MetadataAdapter} [adapter] metadata adapter
* @param {MetadataExtends<T>} [metadataExtends] add extents for metadata.
* @returns
*/
export function createMethodDecorator<T extends MethodMetadata>
createClassMethodDecorator
/**
* create decorator for class and method.
*
* @export
* @template T
* @param {string} name
* @param {MetadataAdapter} [adapter] metadata adapter
* @param {MetadataExtends<T>} [metadataExtends] add extents for metadata.
* @returns {IClassMethodDecorator<T>}
*/
export function createClassMethodDecorator<T extends TypeMetadata>(name: string, adapter?: MetadataAdapter, metadataExtends?: MetadataExtends<T>): IClassMethodDecorator<T>
createParamDecorator
/**
* create parameter decorator.
*
* @export
* @template T metadata type.
* @param {string} name decorator name.
* @param {MetadataAdapter} [adapter] metadata adapter
* @param {MetadataExtends<T>} [metadataExtends] add extents for metadata.
* @returns
*/
export function createParamDecorator<T extends ParameterMetadata>
createPropDecorator
/**
* create property decorator.
*
* @export
* @template T metadata type.
* @param {string} name decorator name.
* @param {MetadataAdapter} [adapter] metadata adapter
* @param {MetadataExtends<T>} [metadataExtends] add extents for metadata.
* @returns
*/
export function createPropDecorator<T extends PropertyMetadata>(name: string, adapter?: MetadataAdapter, metadataExtends?: MetadataExtends<T>): IPropertyDecorator<T>
createParamPropDecorator
/**
* create parameter or property decorator
*
* @export
* @template T
* @param {string} name
* @param {MetadataAdapter} [adapter] metadata adapter
* @param {MetadataExtends<T>} [metadataExtends] add extents for metadata.
* @returns {IParamPropDecorator<T>}
*/
export function createParamPropDecorator<T extends ParamPropMetadata>(
name: string,
adapter?: MetadataAdapter,
metadataExtends?: MetadataExtends<T>): IParamPropDecorator<T>
createDecorator
/**
* create dectorator for class params props methods.
*
* @export
* @template T
* @param {string} name
* @param {MetadataAdapter} [adapter] metadata adapter
* @param {MetadataExtends<T>} [metadataExtends] add extents for metadata.
* @returns {*}
*/
export function createDecorator<T>(name: string, adapter?: MetadataAdapter, metadataExtends?: MetadataExtends<T>): any
Demo fo extends yourself decorator
//eg.
// 1. create decorator
export interface IControllerDecorator<T extends ControllerMetadata> extends IClassDecorator<T> {
(routePrefix: string, provide?: Registration<any> | string, alias?: string): ClassDecorator;
(target: Function): void;
}
export const Controller: IControllerDecorator<ControllerMetadata> =
createClassDecorator<ControllerMetadata>('Controller', (args: ArgsIterator) => {
args.next<ControllerMetadata>({
isMetadata: (arg) => isClassMetadata(arg, ['routePrefix']),
match: (arg) => isString(arg),
setMetadata: (metadata, arg) => {
metadata.routePrefix = arg;
}
});
}) as IControllerDecorator<ControllerMetadata>;
export const Aspect: IClassDecorator<ClassMetadata> = createClassDecorator<ClassMetadata>('Aspect', null, (metadata) => {
metadata.singleton = true;
return metadata;
});
// 2. add decorator action
let lifeScope = container.get(LifeScopeToken);
let factory = new AopActionFactory();
lifeScope.addAction(factory.create(AopActions.registAspect), DecoratorType.Class, IocState.design);
// 3. register decorator
lifeScope.registerDecorator(Aspect, AopActions.registAspect);
Container Interface
see more interface. all document is typescript .d.ts.
Documentation is available on the @ts-ioc/core docs site.
License
MIT © Houjun