dp-ioc2
v1.0.1
Published
简单、强大的基于TypeScript的IOC容器库,支持依赖注入、单例、参数校验等功能
Maintainers
Readme
dp-ioc
简单、强大的基于TypeScript的IOC库。
一、安装 [ Installation ]
- npm i dp-ioc
二、快速开始
import { Inject, Injectable, Provider } from "dp-ioc";
//定义一个可注入类
@Injectable()
class Person {
name = "rajan"
dance() {
return this.name + " dance";
}
}
// 注入到其他类中
class ClassRoom {
@Inject(Person)
public person:Person;
}
// 使用,(通过Provider函数进行实例化 )
let classRoom = Provider<ClassRoom>(ClassRoom);
console.log(classRoom.person.name); // rajan
console.log(classRoom.person.dance); // rajan dance
注意,使用了依赖注入的类,在应用时必须通过Provider进行实例化
三、高级用法
3.1 单例
import { Single, Injectable } from "dp-ioc";
@Single()
@Injectable()
class Person {
name = "rajan"
dance() {
return this.name + " dance";
}
}3.2 多层注入
import { Single, Injectable,Inject,Provider } from "dp-ioc";
@Injectable()
class Person {
name = "rajan"
dance() {
return this.name + " dance";
}
}
@Injectable()
class ClassRoom {
name = "room 001"
@Inject(Person)
person:Person
}
class School {
@Inject(ClassRoom)
classRoom:ClassRoom;
}
let school = Provider<School>(School);
3.3 构造传参
本库支持实例化Injectable可注入对象时,传入实例化的参数
import { Single, Injectable,Inject,Provider,Constructor } from "dp-ioc";
@Injectable()
class Person {
name = "rajan"
age = 0;
//ioc 容器实例化该类时,setPersonBasicInfo方法将会被执行
@Constructor()
setPersonBasicInfo(name:string,age:number){
this.name = name;
this.age = age;
}
dance() {
return this.name + " dance";
}
}
//注入
class ClassRoom {
name = "room 001"
@Inject(Person,["小明",18])
person:Person
}
// 实例化
let classRoom = Provider<ClassRoom>(ClassRoom);
console.log(classRoom.person.name,classRoom.person.age); // 小明 18
3.4 支持继承依赖
import { Single, Injectable,Inject,Provider,Constructor } from "dp-ioc";
@Injectable()
class Human {
age = 0;
name = "";
}
class Student extends Human {
dance():string{
return this.name + "dance";
}
}
class classRoom {
@Inject(Student)
public Student: Student;
}
3.5 序列化和反序列
在实际项目开发中,某些对象可能需要序列化为字符串以便存储,传输。本库支持将序列化之后的对象还原为依赖对象。
import { Single, Injectable,Inject,Provider,Constructor } from "dp-ioc";
@Injectable()
class Person {
age = 0;
name = "";
dance():string{
return this.name + "dance";
}
}
class ClassRoom {
@Inject(Student)
public Student: Student;
}
let classRoom = Provider<ClassRoom>(ClassRoom);
let classRoomStr = JSON.stringify(classRoom); // 序列化为字符串
classRoom = Provider<ClassRoom>(ClassRoom,JSON.parse(classRoomStr)); // 反序列化为依赖对象
3.6 参数校验 (ParamValidate)
本库支持方法参数自动校验,支持 class-validator(对象参数)和 joi(非对象参数)两种校验方式。IOC 容器会自动判断参数类型并选择相应的校验方式。
3.6.1 使用 Joi 校验非对象参数
import { Injectable, Inject, Provider, ParamValidate } from "dp-ioc";
import Joi from "joi";
@Injectable()
class UserService {
// 校验字符串参数
getUserById(@ParamValidate(undefined, Joi.string().min(3).required()) id: string) {
return `User ${id}`;
}
// 校验数字参数
calculate(
@ParamValidate(undefined, Joi.number().min(0).required()) a: number,
@ParamValidate(undefined, Joi.number().min(1).required()) b: number
) {
return a / b;
}
}
class App {
@Inject(UserService)
userService: UserService;
}
const app = Provider<App>(App);
app.userService.getUserById("123"); // ✅ 通过
// app.userService.getUserById("12"); // ❌ 抛出 IOCValidationError3.6.2 使用 class-validator 校验对象参数
import { Injectable, Inject, Provider, ParamValidate } from "dp-ioc";
import { IsString, IsNumber, MinLength, Min } from "class-validator";
// 定义校验类
class CreateUserDto {
@IsString()
@MinLength(3)
name!: string;
@IsNumber()
@Min(18)
age!: number;
}
@Injectable()
class UserService {
async createUser(@ParamValidate(CreateUserDto) user: CreateUserDto) {
return `Created user: ${user.name}, age: ${user.age}`;
}
}
class App {
@Inject(UserService)
userService: UserService;
}
const app = Provider<App>(App);
// ✅ 使用类实例
const user = new CreateUserDto();
user.name = "John";
user.age = 25;
await app.userService.createUser(user);
// ✅ 使用普通对象(会自动转换为类实例)
await app.userService.createUser({ name: "John", age: 25 });
// ❌ 校验失败会抛出 IOCValidationError
// await app.userService.createUser({ name: "Jo", age: 17 });3.6.3 混合使用
import { Injectable, Inject, Provider, ParamValidate } from "dp-ioc";
import Joi from "joi";
import { IsString, MinLength } from "class-validator";
class UserDto {
@IsString()
@MinLength(3)
name!: string;
}
@Injectable()
class UserService {
async updateUser(
@ParamValidate(undefined, Joi.string().min(3).required()) userId: string,
@ParamValidate(UserDto) userData: UserDto
) {
return `Updated user ${userId} with name ${userData.name}`;
}
}3.6.4 错误处理
import { IOCValidationError } from "dp-ioc";
try {
app.userService.getUserById("12");
} catch (error) {
if (error instanceof IOCValidationError) {
console.error("参数校验失败:", error.message);
console.error("详细错误:", error.errors);
}
}注意:
- 参数校验在方法调用前自动执行
- 如果校验失败,会抛出
IOCValidationError异常- 参数校验在 Before hook 之前执行
- 对象参数自动使用 class-validator,非对象参数使用 joi
3.7 方法拦截器 (Interceptor)
拦截器可以完全控制方法的执行流程,包括修改参数、修改返回值、处理错误等。注意:拦截器不能与 Before 和 After 同时使用。
3.7.1 基本使用
import { Injectable, Inject, Provider, Interceptor } from "dp-ioc";
@Injectable()
class Service {
@Interceptor((args: any[], obj: any, targetFn: Function, done: Function) => {
// args: 方法调用的参数列表
// obj: 方法所属的对象实例
// targetFn: 原始的目标方法
// done: 回调函数,用于处理错误或返回结果 (err, result) => void
// 可以修改参数
const modifiedArgs = args.map((arg: number) => arg * 2);
// 调用原始方法
try {
const result = targetFn.apply(obj, modifiedArgs);
done(null, result);
} catch (error) {
done(error, null);
}
})
calculate(a: number, b: number): number {
return a + b;
}
}
class App {
@Inject(Service)
service: Service;
}
const app = Provider<App>(App);
const result = await app.service.calculate(2, 3);
// 参数被修改为 4 和 6,所以结果是 10
console.log(result); // 103.7.2 修改返回值
@Injectable()
class Service {
@Interceptor((args: any[], obj: any, targetFn: Function, done: Function) => {
const result = targetFn.apply(obj, args);
// 修改返回值
done(null, result * 2);
})
add(a: number, b: number): number {
return a + b;
}
}3.7.3 处理异步方法
@Injectable()
class Service {
@Interceptor((args: any[], obj: any, targetFn: Function, done: Function) => {
Promise.resolve(targetFn.apply(obj, args))
.then(result => done(null, result))
.catch(err => done(err, null));
})
async asyncMethod(value: string): Promise<string> {
return new Promise(resolve => {
setTimeout(() => resolve(`async_${value}`), 100);
});
}
}3.7.4 错误处理
@Injectable()
class Service {
@Interceptor((args: any[], obj: any, targetFn: Function, done: Function) => {
try {
const result = targetFn.apply(obj, args);
done(null, result);
} catch (error) {
// 捕获并处理错误
done(new Error(`Intercepted error: ${error}`), null);
}
})
throwError(): void {
throw new Error("Original error");
}
}3.7.5 与参数校验配合使用
import { Injectable, Inject, Provider, Interceptor, ParamValidate } from "dp-ioc";
import Joi from "joi";
@Injectable()
class Service {
@Interceptor((args: any[], obj: any, targetFn: Function, done: Function) => {
// 拦截器在参数校验之后执行
const result = targetFn.apply(obj, args);
done(null, result);
})
test(@ParamValidate(undefined, Joi.string().min(3).required()) value: string): string {
return value;
}
}注意:
- 拦截器不能与 Before 和 After 同时使用,否则会抛出错误
- 拦截器在参数校验之后执行
- 拦截器可以完全控制方法的执行流程
- done 回调函数:第一个参数是错误(如果有),第二个参数是结果
四、支持
如果在使用过程中,遇到问题,请到github仓库反馈,仓库地址。
