fix: 添加skills
This commit is contained in:
340
.claude/skills/repo-core-di/SKILL.md
Normal file
340
.claude/skills/repo-core-di/SKILL.md
Normal file
@@ -0,0 +1,340 @@
|
||||
---
|
||||
name: repo-core-di
|
||||
description: "@repo/core 依赖注入框架使用指南。当需要创建注入器、注册提供者、使用装饰器(@Injectable, @Inject, @Optional等)、处理生命周期(OnInit, OnDestroy)、或解决循环依赖时使用此技能。适用于:(1) 创建和配置注入器层次结构 (2) 注册各类提供者(Value/Class/Factory/Lazy) (3) 使用参数装饰器控制注入行为 (4) 实现服务生命周期管理 (5) 使用 InjectionToken 和 ForwardRef"
|
||||
---
|
||||
|
||||
# @repo/core 依赖注入框架
|
||||
|
||||
## 核心概念
|
||||
|
||||
@repo/core 提供企业级依赖注入框架,支持层次化注入器、多种提供者类型、生命周期管理。
|
||||
|
||||
### 注入器层次结构
|
||||
|
||||
```
|
||||
Root (根注入器)
|
||||
└── Platform (平台注入器)
|
||||
└── Application (应用注入器)
|
||||
└── Feature (特性注入器)
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 创建注入器
|
||||
|
||||
```typescript
|
||||
import { EnvironmentInjector, Injectable, InjectionToken } from '@repo/core'
|
||||
|
||||
// 定义类型安全的令牌
|
||||
const API_URL = new InjectionToken<string>('API_URL')
|
||||
|
||||
// 创建根注入器
|
||||
const rootInjector = EnvironmentInjector.createRootInjector([
|
||||
{ provide: API_URL, useValue: 'https://api.example.com' }
|
||||
])
|
||||
|
||||
// 创建应用注入器(继承根注入器)
|
||||
const appInjector = EnvironmentInjector.createApplicationInjector([
|
||||
UserService,
|
||||
{ provide: LoggerService, useClass: LoggerService }
|
||||
])
|
||||
|
||||
// 初始化(执行所有 @OnInit)
|
||||
await appInjector.init()
|
||||
|
||||
// 获取服务
|
||||
const userService = appInjector.get(UserService)
|
||||
```
|
||||
|
||||
### 使用 @Injectable 装饰器
|
||||
|
||||
```typescript
|
||||
import { Injectable } from '@repo/core'
|
||||
|
||||
// providedIn: 'root' - 单例,自动注册到根注入器
|
||||
@Injectable({ providedIn: 'root' })
|
||||
class ConfigService {
|
||||
apiUrl = 'https://api.example.com'
|
||||
}
|
||||
|
||||
// providedIn: 'auto' - 不自动注册到根注入器,可在任何注入器中被按需解析
|
||||
// 推荐用于请求级服务
|
||||
@Injectable({ providedIn: 'auto' })
|
||||
class RequestScopedService {
|
||||
// 每次请求创建新实例
|
||||
}
|
||||
|
||||
// 使用工厂函数
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
useFactory: (config: ConfigService) => new ApiClient(config.apiUrl),
|
||||
deps: [ConfigService]
|
||||
})
|
||||
class ApiClient {
|
||||
constructor(public baseUrl: string) {}
|
||||
}
|
||||
```
|
||||
|
||||
## 提供者类型
|
||||
|
||||
### 值提供者 (ValueProvider)
|
||||
|
||||
```typescript
|
||||
const API_URL = new InjectionToken<string>('API_URL')
|
||||
const CONFIG_TOKEN = new InjectionToken<AppConfig>('CONFIG_TOKEN')
|
||||
|
||||
{ provide: API_URL, useValue: 'https://api.example.com' }
|
||||
{ provide: CONFIG_TOKEN, useValue: { debug: true, timeout: 5000 } }
|
||||
```
|
||||
|
||||
### 类提供者 (ClassProvider)
|
||||
|
||||
```typescript
|
||||
{ provide: UserService, useClass: UserService }
|
||||
{ provide: Logger, useClass: ConsoleLogger } // 接口映射到实现
|
||||
```
|
||||
|
||||
### 工厂提供者 (FactoryProvider)
|
||||
|
||||
```typescript
|
||||
{
|
||||
provide: DatabaseConnection,
|
||||
useFactory: (config: ConfigService) => {
|
||||
return new DatabaseConnection(config.dbUrl)
|
||||
},
|
||||
deps: [ConfigService]
|
||||
}
|
||||
```
|
||||
|
||||
### 别名提供者 (ExistingProvider)
|
||||
|
||||
```typescript
|
||||
const LOGGER_TOKEN = new InjectionToken<Logger>('Logger')
|
||||
|
||||
{ provide: LOGGER_TOKEN, useExisting: LoggerService }
|
||||
```
|
||||
|
||||
### 延迟提供者 (LazyProvider)
|
||||
|
||||
```typescript
|
||||
const LAZY_CONFIG = new InjectionToken<AppConfig>('LAZY_CONFIG')
|
||||
|
||||
// 延迟类 - 首次访问时才实例化
|
||||
{ provide: HeavyService, useLazyClass: HeavyService }
|
||||
|
||||
// 延迟工厂
|
||||
{ provide: LAZY_CONFIG, useLazyFactory: () => loadConfig(), deps: [] }
|
||||
```
|
||||
|
||||
### 多值提供者 (Multi Provider)
|
||||
|
||||
```typescript
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true }
|
||||
|
||||
// 获取时返回数组
|
||||
const interceptors = injector.get(HTTP_INTERCEPTORS) // [AuthInterceptor, LoggingInterceptor]
|
||||
```
|
||||
|
||||
## 参数装饰器
|
||||
|
||||
### @Inject - 显式指定注入令牌
|
||||
|
||||
```typescript
|
||||
const API_URL = new InjectionToken<string>('API_URL')
|
||||
|
||||
class UserController {
|
||||
constructor(
|
||||
@Inject(UserService) private userService: UserService,
|
||||
@Inject(API_URL) private apiUrl: string
|
||||
) {}
|
||||
}
|
||||
```
|
||||
|
||||
### @Optional - 可选注入
|
||||
|
||||
```typescript
|
||||
class NotificationService {
|
||||
constructor(
|
||||
@Optional(EmailService) private email?: EmailService // 不存在时为 null
|
||||
) {}
|
||||
}
|
||||
```
|
||||
|
||||
### @Self - 仅在当前注入器查找
|
||||
|
||||
```typescript
|
||||
class ChildComponent {
|
||||
constructor(
|
||||
@Self(LocalService) private local: LocalService // 不查找父注入器
|
||||
) {}
|
||||
}
|
||||
```
|
||||
|
||||
### @SkipSelf - 跳过当前注入器
|
||||
|
||||
```typescript
|
||||
class ChildService {
|
||||
constructor(
|
||||
@SkipSelf(ParentService) private parent: ParentService // 从父注入器开始查找
|
||||
) {}
|
||||
}
|
||||
```
|
||||
|
||||
### @Host - 在宿主注入器查找
|
||||
|
||||
```typescript
|
||||
class DirectiveService {
|
||||
constructor(
|
||||
@Host(HostService) private host: HostService
|
||||
) {}
|
||||
}
|
||||
```
|
||||
|
||||
## 生命周期管理
|
||||
|
||||
### @OnInit 装饰器
|
||||
|
||||
```typescript
|
||||
import { Injectable, OnInit } from '@repo/core'
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
class DatabaseService implements OnInit {
|
||||
private connection: Connection
|
||||
|
||||
@OnInit()
|
||||
async onInit() {
|
||||
this.connection = await this.connect()
|
||||
console.log('Database connected')
|
||||
}
|
||||
|
||||
private async connect() {
|
||||
// 连接逻辑
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### OnDestroy 接口
|
||||
|
||||
```typescript
|
||||
import { Injectable, OnDestroy } from '@repo/core'
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
class CacheService implements OnDestroy {
|
||||
async onDestroy() {
|
||||
await this.flush()
|
||||
console.log('Cache flushed')
|
||||
}
|
||||
}
|
||||
|
||||
// 销毁注入器时自动调用
|
||||
await injector.destroy()
|
||||
```
|
||||
|
||||
### APP_INITIALIZER - 应用初始化器
|
||||
|
||||
```typescript
|
||||
import { APP_INITIALIZER, InjectionToken } from '@repo/core'
|
||||
|
||||
const appInjector = EnvironmentInjector.createApplicationInjector([
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useValue: {
|
||||
provide: new InjectionToken('DB_INIT'),
|
||||
deps: [ConfigService],
|
||||
init: async () => {
|
||||
await initDatabase()
|
||||
}
|
||||
},
|
||||
multi: true
|
||||
},
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useValue: {
|
||||
provide: new InjectionToken('CACHE_INIT'),
|
||||
deps: [new InjectionToken('DB_INIT')], // 依赖 DB_INIT
|
||||
init: async () => {
|
||||
await initCache()
|
||||
}
|
||||
},
|
||||
multi: true
|
||||
}
|
||||
])
|
||||
|
||||
// 按依赖顺序执行初始化器
|
||||
await appInjector.init()
|
||||
```
|
||||
|
||||
## InjectionToken
|
||||
|
||||
```typescript
|
||||
import { InjectionToken } from '@repo/core'
|
||||
|
||||
// 创建类型安全的令牌
|
||||
const API_URL = new InjectionToken<string>('API_URL')
|
||||
const CONFIG = new InjectionToken<AppConfig>('CONFIG')
|
||||
const LOGGER_LEVEL = new InjectionToken<LoggerLevel>('LOGGER_LEVEL')
|
||||
|
||||
// 注册
|
||||
const injector = EnvironmentInjector.createRootInjector([
|
||||
{ provide: API_URL, useValue: 'https://api.example.com' },
|
||||
{ provide: CONFIG, useValue: { debug: true } }
|
||||
])
|
||||
|
||||
// 获取(类型安全)
|
||||
const url: string = injector.get(API_URL)
|
||||
const config: AppConfig = injector.get(CONFIG)
|
||||
```
|
||||
|
||||
## ForwardRef - 解决循环依赖
|
||||
|
||||
```typescript
|
||||
import { Injectable, Inject, forwardRef } from '@repo/core'
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
class ServiceA {
|
||||
constructor(
|
||||
@Inject(forwardRef(() => ServiceB)) private serviceB: ServiceB
|
||||
) {}
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
class ServiceB {
|
||||
constructor(
|
||||
@Inject(forwardRef(() => ServiceA)) private serviceA: ServiceA
|
||||
) {}
|
||||
}
|
||||
```
|
||||
|
||||
## 便捷工厂函数
|
||||
|
||||
```typescript
|
||||
import {
|
||||
createRootInjector,
|
||||
createPlatformInjector,
|
||||
createApplicationInjector,
|
||||
createFeatureInjector
|
||||
} from '@repo/core'
|
||||
|
||||
// 简化创建
|
||||
const root = createRootInjector([...providers])
|
||||
const platform = createPlatformInjector([...providers])
|
||||
const app = createApplicationInjector([...providers])
|
||||
const feature = createFeatureInjector([...providers], parentInjector)
|
||||
```
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **使用 providedIn: 'root'** - 大多数服务应该是单例
|
||||
2. **避免循环依赖** - 使用 ForwardRef 仅作为最后手段
|
||||
3. **使用 InjectionToken** - 为非类类型创建类型安全令牌
|
||||
4. **实现 OnDestroy** - 清理资源(连接、订阅等)
|
||||
5. **使用 APP_INITIALIZER** - 管理复杂的初始化顺序
|
||||
6. **延迟加载** - 对重型服务使用 useLazyClass/useLazyFactory
|
||||
|
||||
## 参考文档
|
||||
|
||||
- 详细 API 参考:见 [references/api.md](references/api.md)
|
||||
- 提供者类型详解:见 [references/providers.md](references/providers.md)
|
||||
- 请求级注入器:见 [references/request-scoped-injector.md](references/request-scoped-injector.md) - HTTP 请求隔离、CURRENT_USER 注入、Controller 生命周期
|
||||
- 错误处理系统:见 [references/errors.md](references/errors.md) - 预定义错误类、ErrorFactory、ErrorSerializer
|
||||
Reference in New Issue
Block a user