Files
esengine/packages/core/src/Core/ServiceContainer.ts

425 lines
12 KiB
TypeScript
Raw Normal View History

import { createLogger } from '../Utils/Logger';
2025-10-10 21:52:43 +08:00
import { isUpdatable as checkUpdatable, getUpdatableMetadata } from './DI';
const logger = createLogger('ServiceContainer');
/**
*
* ServiceContainer
*/
export interface IService {
/**
*
*
*/
dispose(): void;
}
/**
*
2025-10-10 21:52:43 +08:00
*
* 便使
* 使 any[]
*/
2025-10-10 21:52:43 +08:00
export type ServiceType<T extends IService> = new (...args: any[]) => T;
/**
*
*/
export enum ServiceLifetime {
/**
* -
*/
Singleton = 'singleton',
/**
* -
*/
Transient = 'transient'
}
/**
*
*/
interface ServiceRegistration<T extends IService> {
/**
*
*/
type: ServiceType<T>;
/**
*
*/
instance?: T;
/**
*
*/
factory?: (container: ServiceContainer) => T;
/**
*
*/
lifetime: ServiceLifetime;
}
/**
*
*
*
*
*
*
* -
* -
* -
* -
*
* @example
* ```typescript
* const container = new ServiceContainer();
*
* // 注册单例服务
* container.registerSingleton(TimerManager);
*
* // 注册工厂函数
* container.registerSingleton(Logger, (c) => createLogger('App'));
*
* // 注册实例
* container.registerInstance(Config, new Config());
*
* // 解析服务
* const timer = container.resolve(TimerManager);
* ```
*/
export class ServiceContainer {
/**
*
*/
private _services: Map<ServiceType<IService>, ServiceRegistration<IService>> = new Map();
/**
*
*/
private _resolving: Set<ServiceType<IService>> = new Set();
2025-10-10 21:52:43 +08:00
/**
*
*
* 使@Updatable装饰器标记的服务Core统一更新
*
*/
private _updatableServices: Array<{ instance: IService; priority: number }> = [];
2025-10-10 21:52:43 +08:00
/**
*
*
* @param type -
* @param factory -
*
* @example
* ```typescript
* // 直接注册类型
* container.registerSingleton(TimerManager);
*
* // 使用工厂函数
* container.registerSingleton(Logger, (c) => {
* return createLogger('App');
* });
* ```
*/
public registerSingleton<T extends IService>(
type: ServiceType<T>,
factory?: (container: ServiceContainer) => T
): void {
if (this._services.has(type as ServiceType<IService>)) {
logger.warn(`Service ${type.name} is already registered`);
return;
}
this._services.set(type as ServiceType<IService>, {
type: type as ServiceType<IService>,
...(factory && { factory: factory as (container: ServiceContainer) => IService }),
lifetime: ServiceLifetime.Singleton
});
logger.debug(`Registered singleton service: ${type.name}`);
}
/**
*
*
*
*
* @param type -
* @param factory -
*
* @example
* ```typescript
* // 每次解析都创建新实例
* container.registerTransient(Command);
* ```
*/
public registerTransient<T extends IService>(
type: ServiceType<T>,
factory?: (container: ServiceContainer) => T
): void {
if (this._services.has(type as ServiceType<IService>)) {
logger.warn(`Service ${type.name} is already registered`);
return;
}
this._services.set(type as ServiceType<IService>, {
type: type as ServiceType<IService>,
...(factory && { factory: factory as (container: ServiceContainer) => IService }),
lifetime: ServiceLifetime.Transient
});
logger.debug(`Registered transient service: ${type.name}`);
}
/**
*
*
*
*
* @param type -
* @param instance -
*
* @example
* ```typescript
* const config = new Config();
* container.registerInstance(Config, config);
* ```
*/
public registerInstance<T extends IService>(type: ServiceType<T>, instance: T): void {
if (this._services.has(type as ServiceType<IService>)) {
logger.warn(`Service ${type.name} is already registered`);
return;
}
this._services.set(type as ServiceType<IService>, {
type: type as ServiceType<IService>,
instance: instance as IService,
lifetime: ServiceLifetime.Singleton
});
2025-10-10 21:52:43 +08:00
// 如果使用了@Updatable装饰器添加到可更新列表
if (checkUpdatable(type)) {
const metadata = getUpdatableMetadata(type);
const priority = metadata?.priority ?? 0;
this._updatableServices.push({ instance, priority });
// 按优先级排序(数值越小越先执行)
this._updatableServices.sort((a, b) => a.priority - b.priority);
logger.debug(`Service ${type.name} is updatable (priority: ${priority}), added to update list`);
}
logger.debug(`Registered service instance: ${type.name}`);
}
/**
*
*
* @param type -
* @returns
* @throws
*
* @example
* ```typescript
* const timer = container.resolve(TimerManager);
* ```
*/
public resolve<T extends IService>(type: ServiceType<T>): T {
const registration = this._services.get(type as ServiceType<IService>);
if (!registration) {
throw new Error(`Service ${type.name} is not registered`);
}
// 检测循环依赖
if (this._resolving.has(type as ServiceType<IService>)) {
const chain = Array.from(this._resolving).map(t => t.name).join(' -> ');
throw new Error(`Circular dependency detected: ${chain} -> ${type.name}`);
}
// 如果是单例且已经有实例,直接返回
if (registration.lifetime === ServiceLifetime.Singleton && registration.instance) {
return registration.instance as T;
}
// 添加到解析栈
this._resolving.add(type as ServiceType<IService>);
try {
// 创建实例
let instance: IService;
if (registration.factory) {
// 使用工厂函数
instance = registration.factory(this);
} else {
// 直接构造
instance = new (registration.type)();
}
// 如果是单例,缓存实例
if (registration.lifetime === ServiceLifetime.Singleton) {
registration.instance = instance;
2025-10-10 21:52:43 +08:00
// 如果使用了@Updatable装饰器添加到可更新列表
if (checkUpdatable(registration.type)) {
const metadata = getUpdatableMetadata(registration.type);
const priority = metadata?.priority ?? 0;
this._updatableServices.push({ instance, priority });
// 按优先级排序(数值越小越先执行)
this._updatableServices.sort((a, b) => a.priority - b.priority);
logger.debug(`Service ${type.name} is updatable (priority: ${priority}), added to update list`);
}
}
return instance as T;
} finally {
// 从解析栈移除
this._resolving.delete(type as ServiceType<IService>);
}
}
/**
*
*
* null而不是抛出异常
*
* @param type -
* @returns null
*
* @example
* ```typescript
* const timer = container.tryResolve(TimerManager);
* if (timer) {
* timer.schedule(...);
* }
* ```
*/
public tryResolve<T extends IService>(type: ServiceType<T>): T | null {
try {
return this.resolve(type);
} catch {
return null;
}
}
/**
*
*
* @param type -
* @returns
*/
public isRegistered<T extends IService>(type: ServiceType<T>): boolean {
return this._services.has(type as ServiceType<IService>);
}
/**
*
*
* @param type -
* @returns
*/
public unregister<T extends IService>(type: ServiceType<T>): boolean {
const registration = this._services.get(type as ServiceType<IService>);
if (!registration) {
return false;
}
// 如果有单例实例,调用 dispose
if (registration.instance) {
2025-10-10 21:52:43 +08:00
// 从可更新列表中移除
const index = this._updatableServices.findIndex(item => item.instance === registration.instance);
if (index !== -1) {
this._updatableServices.splice(index, 1);
}
registration.instance.dispose();
}
this._services.delete(type as ServiceType<IService>);
logger.debug(`Unregistered service: ${type.name}`);
return true;
}
/**
*
*/
public clear(): void {
// 清理所有单例实例
for (const [, registration] of this._services) {
if (registration.instance) {
registration.instance.dispose();
}
}
this._services.clear();
2025-10-10 21:52:43 +08:00
this._updatableServices = [];
logger.debug('Cleared all services');
}
/**
*
*
* @returns
*/
public getRegisteredServices(): ServiceType<IService>[] {
return Array.from(this._services.keys());
}
2025-10-10 21:52:43 +08:00
/**
* 使@Updatable装饰器标记的服务
*
* update方法
* @Updatable装饰器验证过必须实现IUpdatable接口
* Core的主更新循环中调用
*
* @param deltaTime -
*
* @example
* ```typescript
* // 在Core的update方法中
* this._serviceContainer.updateAll(deltaTime);
* ```
*/
public updateAll(deltaTime?: number): void {
for (const { instance } of this._updatableServices) {
(instance as IService & { update: (deltaTime?: number) => void }).update(deltaTime);
2025-10-10 21:52:43 +08:00
}
}
/**
*
*
* @returns
*/
public getUpdatableCount(): number {
return this._updatableServices.length;
}
/**
*
*
* @returns
*/
public getAll(): IService[] {
const instances: IService[] = [];
for (const descriptor of this._services.values()) {
if (descriptor.instance) {
instances.push(descriptor.instance);
}
}
return instances;
}
}