expo-popcore-app/.claude/skills/repo-core-di/references/providers.md

6.3 KiB
Raw Blame History

@repo/core 提供者类型详解

提供者类型概览

类型 用途 示例
ValueProvider 提供静态值 配置、常量
ClassProvider 提供类实例 服务类
FactoryProvider 通过工厂函数创建 需要动态配置的服务
ExistingProvider 别名映射 接口到实现的映射
ConstructorProvider 类本身作为令牌 简化注册
LazyClassProvider 延迟实例化类 重型服务
LazyFactoryProvider 延迟调用工厂 按需加载配置

ValueProvider

直接提供值,不进行实例化。

interface ValueProvider<T> {
  provide: InjectionTokenType<T>
  useValue: T
  multi?: boolean
}

// 示例 - 始终使用 InjectionToken 确保类型安全
const API_URL = new InjectionToken<string>('API_URL')
const CONFIG_TOKEN = new InjectionToken<AppConfig>('CONFIG_TOKEN')
const VERSION = new InjectionToken<string>('VERSION')

{ provide: API_URL, useValue: 'https://api.example.com' }
{ provide: CONFIG_TOKEN, useValue: { debug: true, timeout: 5000 } }
{ provide: VERSION, useValue: '1.0.0' }

适用场景

  • 配置值
  • 常量
  • 已创建的实例
  • 简单对象

ClassProvider

通过构造函数创建实例。

interface ClassProvider<T> {
  provide: InjectionTokenType<T>
  useClass: Type<T>
  multi?: boolean
}

// 示例
{ provide: UserService, useClass: UserService }
{ provide: Logger, useClass: ConsoleLogger }
{ provide: IAuthService, useClass: JwtAuthService }

适用场景

  • 服务类
  • 接口到实现的映射
  • 替换默认实现

FactoryProvider

通过工厂函数创建实例。

interface FactoryProvider<T> {
  provide: InjectionTokenType<T>
  useFactory: (...deps: any[]) => T
  deps?: InjectionTokenType<any>[]
  multi?: boolean
}

// 示例
{
  provide: DatabaseConnection,
  useFactory: (config: ConfigService) => {
    return new DatabaseConnection({
      host: config.dbHost,
      port: config.dbPort,
      database: config.dbName
    })
  },
  deps: [ConfigService]
}

// 异步工厂
{
  provide: RemoteConfig,
  useFactory: async (http: HttpClient) => {
    const config = await http.get('/config')
    return new RemoteConfig(config)
  },
  deps: [HttpClient]
}

适用场景

  • 需要复杂初始化逻辑
  • 依赖运行时配置
  • 条件创建实例
  • 异步初始化

ExistingProvider

创建到另一个令牌的别名。

interface ExistingProvider<T> {
  provide: InjectionTokenType<T>
  useExisting: InjectionTokenType<T>
  multi?: boolean
}

// 示例 - 使用 InjectionToken 确保类型安全
const LOGGER_TOKEN = new InjectionToken<Logger>('Logger')

{ provide: LOGGER_TOKEN, useExisting: LoggerService }
{ provide: AbstractLogger, useExisting: ConsoleLogger }

适用场景

  • 为同一服务提供多个令牌
  • 向后兼容
  • 接口别名

ConstructorProvider

类本身作为令牌和实现。

interface ConstructorProvider<T> {
  provide: Type<T>
  multi?: boolean
}

// 示例
{ provide: UserService }
// 等价于
{ provide: UserService, useClass: UserService }

适用场景

  • 简化注册
  • 类名即令牌

LazyClassProvider

延迟实例化,首次访问时才创建。

interface LazyClassProvider<T> {
  provide: InjectionTokenType<T>
  useLazyClass: Type<T>
  multi?: boolean
}

// 示例
{ provide: HeavyAnalyticsService, useLazyClass: HeavyAnalyticsService }
{ provide: ReportGenerator, useLazyClass: ReportGenerator }

适用场景

  • 重型服务(大量初始化开销)
  • 可能不会使用的服务
  • 优化启动时间

LazyFactoryProvider

延迟调用工厂函数。

interface LazyFactoryProvider<T> {
  provide: InjectionTokenType<T>
  useLazyFactory: (...deps: any[]) => T
  deps?: InjectionTokenType<any>[]
  multi?: boolean
}

// 示例 - 使用 InjectionToken 确保类型安全
const LAZY_CONFIG = new InjectionToken<AppConfig>('LAZY_CONFIG')

{
  provide: LAZY_CONFIG,
  useLazyFactory: async () => {
    const response = await fetch('/api/config')
    return response.json()
  },
  deps: []
}

适用场景

  • 按需加载配置
  • 延迟网络请求
  • 条件初始化

Multi Provider

允许多个提供者注册到同一令牌。

// 注册多个拦截器
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
{ provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true }
{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true }

// 获取时返回数组
const interceptors = injector.get(HTTP_INTERCEPTORS)
// [AuthInterceptor实例, LoggingInterceptor实例, ErrorInterceptor实例]

适用场景

  • 插件系统
  • 中间件/拦截器
  • 事件处理器
  • 验证器集合

提供者选择决策树

需要提供什么?
├── 静态值/配置 → ValueProvider
├── 类实例
│   ├── 简单实例化 → ClassProvider 或 ConstructorProvider
│   ├── 需要复杂初始化 → FactoryProvider
│   ├── 延迟加载 → LazyClassProvider
│   └── 别名/映射 → ExistingProvider
├── 动态值
│   ├── 同步创建 → FactoryProvider
│   └── 延迟创建 → LazyFactoryProvider
└── 多个实现 → 任意类型 + multi: true

常见模式

环境配置

import { InjectionToken } from '@repo/core'

// 定义类型安全的令牌
const ENV = new InjectionToken<string>('ENV')
const API_URL = new InjectionToken<string>('API_URL')

const providers = [
  { provide: ENV, useValue: process.env.NODE_ENV },
  {
    provide: API_URL,
    useFactory: (env: string) => {
      return env === 'production'
        ? 'https://api.prod.com'
        : 'https://api.dev.com'
    },
    deps: [ENV]
  }
]

// 获取时类型安全
const apiUrl: string = injector.get(API_URL)

条件提供者

const providers = [
  process.env.USE_MOCK
    ? { provide: UserService, useClass: MockUserService }
    : { provide: UserService, useClass: RealUserService }
]

工厂链

const providers = [
  { provide: ConfigService, useClass: ConfigService },
  {
    provide: DatabaseService,
    useFactory: (config: ConfigService) => new DatabaseService(config),
    deps: [ConfigService]
  },
  {
    provide: UserRepository,
    useFactory: (db: DatabaseService) => new UserRepository(db),
    deps: [DatabaseService]
  }
]