tsioc is AOP, Ioc container, via typescript decorator
npm install @ts-ioc/corenpm. The source for this module is in the
@ts-ioc/core is AOP, Ioc container, via typescript decorator.
tsioc
shell
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
`shell
npm install @ts-ioc/core
// in browser
npm install @ts-ioc/platform-browser
// in server
npm install @ts-ioc/platform-server
`
add extends modules
$3
`shell
// install aop
npm install @ts-ioc/aop
`
`ts
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);
`
$3
`shell
// install aop logs
npm install @ts-ioc/logs
`
`ts
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
1. Register one class will auto register depdence class (must has a class decorator).
2. get Instance can auto create constructor param. (must has a class decorator or register in container).
$3
1. @Abstract abstract class decorator.
2. @AutoRun class, method decorator, use to define the class auto run (via a method or not) after registered.
3. @AutoWried property or param decorator, use to auto wried type instance or value to the instance of one class with the decorator.
4. @Component class decortator, use to define the class. it can setting provider to some token, singleton or not. it will execute ComponentLifecycle hooks when create a instance .
5. @Inject property or param decorator, use to auto wried type instance or value to the instance of one class with the decorator.
6. @Injectable class decortator, use to define the class. it can setting provider to some token, singleton or not.
7. @IocExt class decortator, use to define the class is Ioc extends module. it will auto run after registered to helper your to setup module.
8. @Method method decorator.
9. @Param param decorator, use to auto wried type instance or value to the instance of one class with the decorator.
10. @Singleton class decortator, use to define the class is singleton.
11. @Providers Providers decorator, for class. use to add private ref service for the class.
12. @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
mvc boot simple
`ts
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
* activities
* build
* pack
$3
* in browser can not:
1. use syncBuild
2. syncLoadModule
3. can not use minimatch to match file.
4. support es5 uglify, @ts-ioc/annotations [] or typescript-class-annotations to get class annotations before typescript compile.
`ts
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]
});
`
$3
see interface IContainer
`ts
// 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));
`
$3
`ts
// 8. get instance use get method of container.
/**
* resolve type instance with token and param provider.
*
* @template T
* @param {Token} token
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IResolver
*/
resolve(token: Token, ...providers: ProviderTypes[]): T;
/**
* Retrieves an instance from the container based on the provided token.
*
* @template T
* @param {Token} token
* @param {string} [alias]
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
get(token: Token, alias?: string, ...providers: ProviderTypes[]): T;
/**
* resolve token value in this container only.
*
* @template T
* @param {Token} token
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
resolveValue(token: Token, ...providers: ProviderTypes[]): T;
/**
* get service or target reference service.
*
* @template T
* @param {Token} token servive token.
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
getService(token: Token, ...providers: ProviderTypes[]): T;
/**
* get service or target reference service.
*
* @template T
* @param {Token} token servive token.
* @param {(Token | Token[])} [target] service refrence target.
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
getService(token: Token, target: Token | Token[], ...providers: ProviderTypes[]): T;
/**
* get service or target reference service.
*
* @template T
* @param {Token} token servive token.
* @param {(Token | Token[])} [target] service refrence target.
* @param {RefTokenFac} toRefToken
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
getService(token: Token, target: Token | Token[], toRefToken: RefTokenFac, ...providers: ProviderTypes[]): T;
/**
* get service or target reference service.
*
* @template T
* @param {Token} token servive token.
* @param {(Token | Token[])} [target] service refrence target.
* @param {(boolean | Token)} defaultToken
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
getService(token: Token, target: Token | Token[], defaultToken: boolean | Token, ...providers: ProviderTypes[]): T;
/**
* get service or target reference service.
*
* @template T
* @param {Token} token servive token.
* @param {(Token | Token[])} [target] service refrence target.
* @param {RefTokenFac} toRefToken
* @param {(boolean | Token)} defaultToken
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
getService(token: Token, target: Token | Token[], toRefToken: RefTokenFac, defaultToken: boolean | Token, ...providers: ProviderTypes[]): T;
/**
* get target reference service.
*
* @template T
* @param {ReferenceToken} [refToken] reference service Registration Injector
* @param {(Token | Token[])} target the service reference to.
* @param {Token} [defaultToken] default service token.
* @param {...ProviderTypes[]} providers
* @returns {T}
* @memberof IContainer
*/
getRefService(refToken: ReferenceToken, target: Token | Token[], defaultToken?: Token, ...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);
`
$3
you can use yourself MethodAccessor by implement IMethodAccessor, register MethodAccessorToken with your MethodAccessor in container, see interface IMethodAccessor.
`ts
@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, 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, 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
`ts
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:
1. createClassDecorator
`ts
/**
* create class decorator
*
* @export
* @template T metadata type.
* @param {string} name decorator name.
* @param {MetadataAdapter} [adapter] metadata adapter
* @param {MetadataExtends} [metadataExtends] add extents for metadata.
@returns {}
*/
export function createClassDecorator(name: string, adapter?: MetadataAdapter, metadataExtends?: MetadataExtends): IClassDecorator
`
2. createClassMethodDecorator
`ts
/**
* create method decorator.
*
* @export
* @template T metadata type.
* @param {string} name decorator name.
* @param {MetadataAdapter} [adapter] metadata adapter
* @param {MetadataExtends} [metadataExtends] add extents for metadata.
* @returns
*/
export function createMethodDecorator
`
3. createClassMethodDecorator
`ts
/**
* create decorator for class and method.
*
* @export
* @template T
* @param {string} name
* @param {MetadataAdapter} [adapter] metadata adapter
* @param {MetadataExtends} [metadataExtends] add extents for metadata.
* @returns {IClassMethodDecorator}
*/
export function createClassMethodDecorator(name: string, adapter?: MetadataAdapter, metadataExtends?: MetadataExtends): IClassMethodDecorator
`
4. createParamDecorator
`ts
/**
* create parameter decorator.
*
* @export
* @template T metadata type.
* @param {string} name decorator name.
* @param {MetadataAdapter} [adapter] metadata adapter
* @param {MetadataExtends} [metadataExtends] add extents for metadata.
* @returns
*/
export function createParamDecorator
`
5. createPropDecorator
`ts
/**
* create property decorator.
*
* @export
* @template T metadata type.
* @param {string} name decorator name.
* @param {MetadataAdapter} [adapter] metadata adapter
* @param {MetadataExtends} [metadataExtends] add extents for metadata.
* @returns
*/
export function createPropDecorator(name: string, adapter?: MetadataAdapter, metadataExtends?: MetadataExtends): IPropertyDecorator
`
6. createParamPropDecorator
`ts
/**
* create parameter or property decorator
*
* @export
* @template T
* @param {string} name
* @param {MetadataAdapter} [adapter] metadata adapter
* @param {MetadataExtends} [metadataExtends] add extents for metadata.
* @returns {IParamPropDecorator}
*/
export function createParamPropDecorator(
name: string,
adapter?: MetadataAdapter,
metadataExtends?: MetadataExtends): IParamPropDecorator
`
7. createDecorator
`ts
/**
* create dectorator for class params props methods.
*
* @export
* @template T
* @param {string} name
* @param {MetadataAdapter} [adapter] metadata adapter
* @param {MetadataExtends} [metadataExtends] add extents for metadata.
@returns {}
*/
export function createDecorator(name: string, adapter?: MetadataAdapter, metadataExtends?: MetadataExtends): any
`
$3
`ts
//eg.
// 1. create decorator
export interface IControllerDecorator extends IClassDecorator {
(routePrefix: string, provide?: Registration | string, alias?: string): ClassDecorator;
(target: Function): void;
}
export const Controller: IControllerDecorator =
createClassDecorator('Controller', (args: ArgsIterator) => {
args.next({
isMetadata: (arg) => isClassMetadata(arg, ['routePrefix']),
match: (arg) => isString(arg),
setMetadata: (metadata, arg) => {
metadata.routePrefix = arg;
}
});
}) as IControllerDecorator;
export const Aspect: IClassDecorator = createClassDecorator('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);
``