新增ServiceContainer服务容器, 所有服务统一实现 IService 接口
This commit is contained in:
@@ -10,6 +10,7 @@ import { ICoreConfig, IECSDebugConfig } from './Types';
|
||||
import { createLogger } from './Utils/Logger';
|
||||
import { SceneManager } from './ECS/SceneManager';
|
||||
import { IScene } from './ECS/IScene';
|
||||
import { ServiceContainer } from './Core/ServiceContainer';
|
||||
|
||||
/**
|
||||
* 游戏引擎核心类
|
||||
@@ -76,6 +77,13 @@ export class Core {
|
||||
*/
|
||||
public readonly debug: boolean;
|
||||
|
||||
/**
|
||||
* 服务容器
|
||||
*
|
||||
* 管理所有服务的注册、解析和生命周期。
|
||||
*/
|
||||
private _serviceContainer: ServiceContainer;
|
||||
|
||||
/**
|
||||
* 全局管理器集合
|
||||
*
|
||||
@@ -138,23 +146,29 @@ export class Core {
|
||||
...config
|
||||
};
|
||||
|
||||
// 初始化服务容器
|
||||
this._serviceContainer = new ServiceContainer();
|
||||
|
||||
// 初始化定时器管理器
|
||||
this._timerManager = new TimerManager();
|
||||
Core.registerGlobalManager(this._timerManager);
|
||||
this._serviceContainer.registerInstance(TimerManager, this._timerManager);
|
||||
|
||||
// 初始化性能监控器
|
||||
this._performanceMonitor = PerformanceMonitor.instance;
|
||||
this._performanceMonitor = new PerformanceMonitor();
|
||||
this._serviceContainer.registerInstance(PerformanceMonitor, this._performanceMonitor);
|
||||
|
||||
// 在调试模式下启用性能监控
|
||||
if (this._config.debug) {
|
||||
this._performanceMonitor.enable();
|
||||
}
|
||||
|
||||
// 初始化对象池管理器
|
||||
// 初始化对象池管理器(单例模式)
|
||||
this._poolManager = PoolManager.getInstance();
|
||||
|
||||
// 初始化场景管理器
|
||||
this._sceneManager = new SceneManager();
|
||||
this._serviceContainer.registerInstance(SceneManager, this._sceneManager);
|
||||
|
||||
Core.entitySystemsEnabled = this._config.enableEntitySystems ?? true;
|
||||
this.debug = this._config.debug ?? true;
|
||||
@@ -162,6 +176,7 @@ export class Core {
|
||||
// 初始化调试管理器
|
||||
if (this._config.debugConfig?.enabled) {
|
||||
this._debugManager = new DebugManager(this, this._config.debugConfig);
|
||||
this._serviceContainer.registerInstance(DebugManager, this._debugManager);
|
||||
}
|
||||
|
||||
this.initialize();
|
||||
@@ -176,6 +191,29 @@ export class Core {
|
||||
return this._instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务容器
|
||||
*
|
||||
* 用于注册和解析自定义服务。
|
||||
*
|
||||
* @returns 服务容器实例
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // 注册自定义服务
|
||||
* Core.services.registerSingleton(MyService);
|
||||
*
|
||||
* // 解析服务
|
||||
* const myService = Core.services.resolve(MyService);
|
||||
* ```
|
||||
*/
|
||||
public static get services(): ServiceContainer {
|
||||
if (!this._instance) {
|
||||
throw new Error('Core实例未创建,请先调用Core.create()');
|
||||
}
|
||||
return this._instance._serviceContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Core实例
|
||||
*
|
||||
|
||||
334
packages/core/src/Core/ServiceContainer.ts
Normal file
334
packages/core/src/Core/ServiceContainer.ts
Normal file
@@ -0,0 +1,334 @@
|
||||
import { createLogger } from '../Utils/Logger';
|
||||
|
||||
const logger = createLogger('ServiceContainer');
|
||||
|
||||
/**
|
||||
* 服务基础接口
|
||||
* 所有通过 ServiceContainer 管理的服务都应该实现此接口
|
||||
*/
|
||||
export interface IService {
|
||||
/**
|
||||
* 释放服务占用的资源
|
||||
* 当服务被注销或容器被清空时调用
|
||||
*/
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务类型
|
||||
*/
|
||||
export type ServiceType<T extends IService> = new (...args: unknown[]) => 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();
|
||||
|
||||
/**
|
||||
* 注册单例服务
|
||||
*
|
||||
* @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 as ((container: ServiceContainer) => IService) | undefined,
|
||||
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 as ((container: ServiceContainer) => IService) | undefined,
|
||||
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: new (...args: any[]) => 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
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
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();
|
||||
logger.debug('Cleared all services');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有已注册的服务类型
|
||||
*
|
||||
* @returns 服务类型数组
|
||||
*/
|
||||
public getRegisteredServices(): ServiceType<IService>[] {
|
||||
return Array.from(this._services.keys());
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,8 @@ import { TypedQueryBuilder } from './Core/Query/TypedQuery';
|
||||
import { SceneSerializer, SceneSerializationOptions, SceneDeserializationOptions } from './Serialization/SceneSerializer';
|
||||
import { IncrementalSerializer, IncrementalSnapshot, IncrementalSerializationOptions } from './Serialization/IncrementalSerializer';
|
||||
import { ComponentPoolManager } from './Core/ComponentPool';
|
||||
import { PerformanceMonitor } from '../Utils/PerformanceMonitor';
|
||||
import { Core } from '../Core';
|
||||
|
||||
/**
|
||||
* 游戏场景默认实现类
|
||||
@@ -423,8 +425,13 @@ export class Scene implements IScene {
|
||||
if (this.entityProcessors.processors.includes(processor)) {
|
||||
return processor;
|
||||
}
|
||||
|
||||
|
||||
processor.scene = this;
|
||||
|
||||
// 从Core获取PerformanceMonitor并注入到System
|
||||
const perfMonitor = Core.services.resolve(PerformanceMonitor);
|
||||
processor.setPerformanceMonitor(perfMonitor);
|
||||
|
||||
this.entityProcessors.add(processor);
|
||||
processor.initialize();
|
||||
processor.setUpdateOrder(this.entityProcessors.count - 1);
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ECSFluentAPI, createECSAPI } from './Core/FluentAPI';
|
||||
import { Time } from '../Utils/Time';
|
||||
import { Core } from '../Core';
|
||||
import { createLogger } from '../Utils/Logger';
|
||||
import type { IService } from '../Core/ServiceContainer';
|
||||
|
||||
/**
|
||||
* 单场景管理器
|
||||
@@ -46,7 +47,7 @@ import { createLogger } from '../Utils/Logger';
|
||||
* sceneManager.loadScene(new MenuScene());
|
||||
* ```
|
||||
*/
|
||||
export class SceneManager {
|
||||
export class SceneManager implements IService {
|
||||
/**
|
||||
* 当前活跃场景
|
||||
*/
|
||||
@@ -235,4 +236,11 @@ export class SceneManager {
|
||||
public get hasPendingScene(): boolean {
|
||||
return this._nextScene !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放资源(IService接口)
|
||||
*/
|
||||
public dispose(): void {
|
||||
this.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ export abstract class EntitySystem<
|
||||
> implements ISystemBase {
|
||||
private _updateOrder: number;
|
||||
private _enabled: boolean;
|
||||
private _performanceMonitor: PerformanceMonitor;
|
||||
private _performanceMonitor: PerformanceMonitor | null;
|
||||
private _systemName: string;
|
||||
private _initialized: boolean;
|
||||
private _matcher: Matcher;
|
||||
@@ -148,7 +148,7 @@ export abstract class EntitySystem<
|
||||
constructor(matcher?: Matcher) {
|
||||
this._updateOrder = 0;
|
||||
this._enabled = true;
|
||||
this._performanceMonitor = PerformanceMonitor.instance;
|
||||
this._performanceMonitor = null;
|
||||
this._systemName = getSystemInstanceTypeName(this);
|
||||
this._initialized = false;
|
||||
this._matcher = matcher || Matcher.empty();
|
||||
@@ -192,6 +192,23 @@ export abstract class EntitySystem<
|
||||
this._scene = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置性能监控器
|
||||
*/
|
||||
public setPerformanceMonitor(monitor: PerformanceMonitor): void {
|
||||
this._performanceMonitor = monitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取性能监控器
|
||||
*/
|
||||
private getPerformanceMonitor(): PerformanceMonitor {
|
||||
if (!this._performanceMonitor) {
|
||||
throw new Error(`${this._systemName}: PerformanceMonitor未注入,请确保在Core.create()之后再添加System到Scene`);
|
||||
}
|
||||
return this._performanceMonitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实体匹配器
|
||||
*/
|
||||
@@ -533,7 +550,8 @@ export abstract class EntitySystem<
|
||||
return;
|
||||
}
|
||||
|
||||
const startTime = this._performanceMonitor.startMonitoring(this._systemName);
|
||||
const monitor = this.getPerformanceMonitor();
|
||||
const startTime = monitor.startMonitoring(this._systemName);
|
||||
let entityCount = 0;
|
||||
|
||||
try {
|
||||
@@ -544,7 +562,7 @@ export abstract class EntitySystem<
|
||||
|
||||
this.process(this._entityCache.frame);
|
||||
} finally {
|
||||
this._performanceMonitor.endMonitoring(this._systemName, startTime, entityCount);
|
||||
monitor.endMonitoring(this._systemName, startTime, entityCount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,7 +574,8 @@ export abstract class EntitySystem<
|
||||
return;
|
||||
}
|
||||
|
||||
const startTime = this._performanceMonitor.startMonitoring(`${this._systemName}_Late`);
|
||||
const monitor = this.getPerformanceMonitor();
|
||||
const startTime = monitor.startMonitoring(`${this._systemName}_Late`);
|
||||
let entityCount = 0;
|
||||
|
||||
try {
|
||||
@@ -566,7 +585,7 @@ export abstract class EntitySystem<
|
||||
this.lateProcess(entities);
|
||||
this.onEnd();
|
||||
} finally {
|
||||
this._performanceMonitor.endMonitoring(`${this._systemName}_Late`, startTime, entityCount);
|
||||
monitor.endMonitoring(`${this._systemName}_Late`, startTime, entityCount);
|
||||
// 清理帧缓存
|
||||
this._entityCache.clearFrame();
|
||||
}
|
||||
@@ -626,27 +645,27 @@ export abstract class EntitySystem<
|
||||
|
||||
/**
|
||||
* 获取系统的性能数据
|
||||
*
|
||||
*
|
||||
* @returns 性能数据或undefined
|
||||
*/
|
||||
public getPerformanceData() {
|
||||
return this._performanceMonitor.getSystemData(this._systemName);
|
||||
return this.getPerformanceMonitor().getSystemData(this._systemName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统的性能统计
|
||||
*
|
||||
*
|
||||
* @returns 性能统计或undefined
|
||||
*/
|
||||
public getPerformanceStats() {
|
||||
return this._performanceMonitor.getSystemStats(this._systemName);
|
||||
return this.getPerformanceMonitor().getSystemStats(this._systemName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置系统的性能数据
|
||||
*/
|
||||
public resetPerformanceData(): void {
|
||||
this._performanceMonitor.resetSystem(this._systemName);
|
||||
this.getPerformanceMonitor().resetSystem(this._systemName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,13 +9,14 @@ import { Component } from '../../ECS/Component';
|
||||
import { ComponentPoolManager } from '../../ECS/Core/ComponentPool';
|
||||
import { Pool } from '../../Utils/Pool';
|
||||
import { getComponentInstanceTypeName, getSystemInstanceTypeName } from '../../ECS/Decorators';
|
||||
import type { IService } from '../../Core/ServiceContainer';
|
||||
|
||||
/**
|
||||
* 调试管理器
|
||||
*
|
||||
* 整合所有调试数据收集器,负责收集和发送调试数据
|
||||
*/
|
||||
export class DebugManager {
|
||||
export class DebugManager implements IService {
|
||||
private config: IECSDebugConfig;
|
||||
private webSocketManager: WebSocketManager;
|
||||
private entityCollector: EntityDataCollector;
|
||||
@@ -821,4 +822,11 @@ export class DebugManager {
|
||||
// console.error('[ECS Debug] 发送调试数据失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放资源
|
||||
*/
|
||||
public dispose(): void {
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
@@ -99,20 +99,20 @@ export interface PerformanceThresholds {
|
||||
};
|
||||
}
|
||||
|
||||
import type { IService } from '../Core/ServiceContainer';
|
||||
|
||||
/**
|
||||
* 高性能监控器
|
||||
* 用于监控ECS系统的性能表现,提供详细的分析和优化建议
|
||||
*/
|
||||
export class PerformanceMonitor {
|
||||
private static _instance: PerformanceMonitor;
|
||||
|
||||
export class PerformanceMonitor implements IService {
|
||||
private _systemData = new Map<string, PerformanceData>();
|
||||
private _systemStats = new Map<string, PerformanceStats>();
|
||||
private _warnings: PerformanceWarning[] = [];
|
||||
private _isEnabled = false;
|
||||
private _maxRecentSamples = 60; // 保留最近60帧的数据
|
||||
private _maxWarnings = 100; // 最大警告数量
|
||||
|
||||
|
||||
// 性能阈值配置
|
||||
private _thresholds: PerformanceThresholds = {
|
||||
executionTime: { warning: 16.67, critical: 33.33 }, // 60fps和30fps对应的帧时间
|
||||
@@ -139,18 +139,8 @@ export class PerformanceMonitor {
|
||||
private _gcCount = 0;
|
||||
private _lastGcCheck = 0;
|
||||
private _gcCheckInterval = 1000;
|
||||
|
||||
/**
|
||||
* 获取单例实例
|
||||
*/
|
||||
public static get instance(): PerformanceMonitor {
|
||||
if (!PerformanceMonitor._instance) {
|
||||
PerformanceMonitor._instance = new PerformanceMonitor();
|
||||
}
|
||||
return PerformanceMonitor._instance;
|
||||
}
|
||||
|
||||
private constructor() {}
|
||||
constructor() {}
|
||||
|
||||
/**
|
||||
* 启用性能监控
|
||||
@@ -392,7 +382,7 @@ export class PerformanceMonitor {
|
||||
*/
|
||||
public setMaxRecentSamples(maxSamples: number): void {
|
||||
this._maxRecentSamples = maxSamples;
|
||||
|
||||
|
||||
// 裁剪现有数据
|
||||
for (const stats of this._systemStats.values()) {
|
||||
while (stats.recentTimes.length > maxSamples) {
|
||||
@@ -400,4 +390,16 @@ export class PerformanceMonitor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放资源
|
||||
*/
|
||||
public dispose(): void {
|
||||
this._systemData.clear();
|
||||
this._systemStats.clear();
|
||||
this._warnings = [];
|
||||
this._fpsHistory = [];
|
||||
this._memoryHistory = [];
|
||||
this._isEnabled = false;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
import { GlobalManager } from '../GlobalManager';
|
||||
import { Timer } from './Timer';
|
||||
import { ITimer } from './ITimer';
|
||||
import type { IService } from '../../Core/ServiceContainer';
|
||||
|
||||
/**
|
||||
* 允许动作的延迟和重复执行
|
||||
*/
|
||||
export class TimerManager extends GlobalManager {
|
||||
export class TimerManager extends GlobalManager implements IService {
|
||||
public _timers: Array<Timer<unknown>> = [];
|
||||
|
||||
public override update() {
|
||||
@@ -31,4 +32,14 @@ export class TimerManager extends GlobalManager {
|
||||
|
||||
return timer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放资源
|
||||
*/
|
||||
public dispose(): void {
|
||||
for (const timer of this._timers) {
|
||||
timer.unload();
|
||||
}
|
||||
this._timers = [];
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
// 核心模块
|
||||
export { Core } from './Core';
|
||||
export { ServiceContainer, ServiceLifetime } from './Core/ServiceContainer';
|
||||
export type { IService, ServiceType } from './Core/ServiceContainer';
|
||||
|
||||
// 核心管理器
|
||||
export { Emitter, FuncPack } from './Utils/Emitter';
|
||||
|
||||
235
packages/core/tests/Core/ServiceContainer.test.ts
Normal file
235
packages/core/tests/Core/ServiceContainer.test.ts
Normal file
@@ -0,0 +1,235 @@
|
||||
import { ServiceContainer, ServiceLifetime } from '../../src/Core/ServiceContainer';
|
||||
|
||||
// 测试服务类
|
||||
class TestService {
|
||||
public value: number = 0;
|
||||
|
||||
constructor() {
|
||||
this.value = Math.random();
|
||||
}
|
||||
|
||||
dispose() {
|
||||
// 清理资源
|
||||
}
|
||||
}
|
||||
|
||||
class DependentService {
|
||||
public testService?: TestService;
|
||||
|
||||
constructor(...args: unknown[]) {
|
||||
this.testService = args[0] as TestService | undefined;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
// 清理资源
|
||||
}
|
||||
}
|
||||
|
||||
class DisposableService {
|
||||
public disposed = false;
|
||||
|
||||
dispose() {
|
||||
this.disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
describe('ServiceContainer - 服务容器测试', () => {
|
||||
let container: ServiceContainer;
|
||||
|
||||
beforeEach(() => {
|
||||
container = new ServiceContainer();
|
||||
});
|
||||
|
||||
describe('单例服务注册', () => {
|
||||
test('应该能够注册单例服务', () => {
|
||||
container.registerSingleton(TestService);
|
||||
expect(container.isRegistered(TestService)).toBe(true);
|
||||
});
|
||||
|
||||
test('单例服务应该返回相同实例', () => {
|
||||
container.registerSingleton(TestService);
|
||||
|
||||
const instance1 = container.resolve(TestService);
|
||||
const instance2 = container.resolve(TestService);
|
||||
|
||||
expect(instance1).toBe(instance2);
|
||||
expect(instance1.value).toBe(instance2.value);
|
||||
});
|
||||
|
||||
test('应该能够使用工厂函数注册单例', () => {
|
||||
const fixedValue = 42;
|
||||
container.registerSingleton(TestService, () => {
|
||||
const service = new TestService();
|
||||
service.value = fixedValue;
|
||||
return service;
|
||||
});
|
||||
|
||||
const instance = container.resolve(TestService);
|
||||
expect(instance.value).toBe(fixedValue);
|
||||
});
|
||||
});
|
||||
|
||||
describe('瞬时服务注册', () => {
|
||||
test('应该能够注册瞬时服务', () => {
|
||||
container.registerTransient(TestService);
|
||||
expect(container.isRegistered(TestService)).toBe(true);
|
||||
});
|
||||
|
||||
test('瞬时服务应该每次返回新实例', () => {
|
||||
container.registerTransient(TestService);
|
||||
|
||||
const instance1 = container.resolve(TestService);
|
||||
const instance2 = container.resolve(TestService);
|
||||
|
||||
expect(instance1).not.toBe(instance2);
|
||||
expect(instance1.value).not.toBe(instance2.value);
|
||||
});
|
||||
});
|
||||
|
||||
describe('实例注册', () => {
|
||||
test('应该能够注册已存在的实例', () => {
|
||||
const instance = new TestService();
|
||||
instance.value = 99;
|
||||
|
||||
container.registerInstance(TestService, instance);
|
||||
|
||||
const resolved = container.resolve(TestService);
|
||||
expect(resolved).toBe(instance);
|
||||
expect(resolved.value).toBe(99);
|
||||
});
|
||||
});
|
||||
|
||||
describe('服务解析', () => {
|
||||
test('解析未注册的服务应该抛出错误', () => {
|
||||
expect(() => container.resolve(TestService)).toThrow(
|
||||
'Service TestService is not registered'
|
||||
);
|
||||
});
|
||||
|
||||
test('tryResolve应该返回null而不是抛出错误', () => {
|
||||
const result = container.tryResolve(TestService);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
test('tryResolve应该返回已注册的服务', () => {
|
||||
container.registerSingleton(TestService);
|
||||
const result = container.tryResolve(TestService);
|
||||
expect(result).not.toBeNull();
|
||||
expect(result).toBeInstanceOf(TestService);
|
||||
});
|
||||
});
|
||||
|
||||
describe('依赖注入', () => {
|
||||
test('工厂函数应该能够解析其他服务', () => {
|
||||
container.registerSingleton(TestService);
|
||||
container.registerSingleton(DependentService, (c) => {
|
||||
const testService = c.resolve(TestService);
|
||||
return new DependentService(testService);
|
||||
});
|
||||
|
||||
const dependent = container.resolve(DependentService);
|
||||
const test = container.resolve(TestService);
|
||||
|
||||
expect(dependent.testService).toBe(test);
|
||||
});
|
||||
});
|
||||
|
||||
describe('循环依赖检测', () => {
|
||||
test('应该检测并报告循环依赖', () => {
|
||||
class ServiceA {
|
||||
constructor() {
|
||||
// 在构造函数中尝试解析ServiceB会导致循环依赖
|
||||
}
|
||||
dispose() {}
|
||||
}
|
||||
|
||||
class ServiceB {
|
||||
constructor() {}
|
||||
dispose() {}
|
||||
}
|
||||
|
||||
container.registerSingleton(ServiceA, (c) => {
|
||||
c.resolve(ServiceB); // 尝试解析B
|
||||
return new ServiceA();
|
||||
});
|
||||
|
||||
container.registerSingleton(ServiceB, (c) => {
|
||||
c.resolve(ServiceA); // 尝试解析A
|
||||
return new ServiceB();
|
||||
});
|
||||
|
||||
expect(() => container.resolve(ServiceA)).toThrow(/Circular dependency detected/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('服务注销', () => {
|
||||
test('应该能够注销服务', () => {
|
||||
container.registerSingleton(TestService);
|
||||
expect(container.isRegistered(TestService)).toBe(true);
|
||||
|
||||
const result = container.unregister(TestService);
|
||||
expect(result).toBe(true);
|
||||
expect(container.isRegistered(TestService)).toBe(false);
|
||||
});
|
||||
|
||||
test('注销不存在的服务应该返回false', () => {
|
||||
const result = container.unregister(TestService);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
test('注销服务应该调用dispose方法', () => {
|
||||
const instance = new DisposableService();
|
||||
container.registerInstance(DisposableService, instance);
|
||||
|
||||
container.unregister(DisposableService);
|
||||
expect(instance.disposed).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('清空容器', () => {
|
||||
test('应该能够清空所有服务', () => {
|
||||
container.registerSingleton(TestService);
|
||||
container.registerTransient(DependentService);
|
||||
|
||||
expect(container.getRegisteredServices().length).toBe(2);
|
||||
|
||||
container.clear();
|
||||
|
||||
expect(container.getRegisteredServices().length).toBe(0);
|
||||
});
|
||||
|
||||
test('清空容器应该调用所有单例的dispose方法', () => {
|
||||
const instance = new DisposableService();
|
||||
container.registerInstance(DisposableService, instance);
|
||||
|
||||
container.clear();
|
||||
expect(instance.disposed).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('重复注册', () => {
|
||||
test('重复注册应该发出警告但不覆盖', () => {
|
||||
container.registerSingleton(TestService);
|
||||
const instance1 = container.resolve(TestService);
|
||||
|
||||
// 尝试重复注册
|
||||
container.registerSingleton(TestService);
|
||||
const instance2 = container.resolve(TestService);
|
||||
|
||||
// 应该返回相同的实例(没有被覆盖)
|
||||
expect(instance1).toBe(instance2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('获取已注册服务列表', () => {
|
||||
test('应该返回所有已注册的服务类型', () => {
|
||||
container.registerSingleton(TestService);
|
||||
container.registerTransient(DependentService);
|
||||
|
||||
const services = container.getRegisteredServices();
|
||||
expect(services).toContain(TestService);
|
||||
expect(services).toContain(DependentService);
|
||||
expect(services.length).toBe(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -7,6 +7,7 @@ import { Component } from '../../../src/ECS/Component';
|
||||
import { ComponentRegistry } from '../../../src/ECS/Core/ComponentStorage';
|
||||
import { Time } from '../../../src/Utils/Time';
|
||||
import { Matcher } from '../../../src/ECS/Utils/Matcher';
|
||||
import { Core } from '../../../src/Core';
|
||||
|
||||
// 测试组件
|
||||
class TestComponent extends Component {
|
||||
@@ -83,6 +84,7 @@ describe('System Types - 系统类型测试', () => {
|
||||
let entity: Entity;
|
||||
|
||||
beforeEach(() => {
|
||||
Core.create();
|
||||
scene = new Scene();
|
||||
entity = scene.createEntity('TestEntity');
|
||||
// 重置时间系统
|
||||
@@ -97,6 +99,7 @@ describe('System Types - 系统类型测试', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
passiveSystem = new ConcretePassiveSystem();
|
||||
scene.addEntityProcessor(passiveSystem);
|
||||
});
|
||||
|
||||
test('应该能够创建被动系统', () => {
|
||||
@@ -136,6 +139,7 @@ describe('System Types - 系统类型测试', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
intervalSystem = new ConcreteIntervalSystem(testInterval);
|
||||
scene.addEntityProcessor(intervalSystem);
|
||||
});
|
||||
|
||||
test('应该能够创建间隔系统', () => {
|
||||
@@ -218,6 +222,7 @@ describe('System Types - 系统类型测试', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
processingSystem = new ConcreteProcessingSystem();
|
||||
scene.addEntityProcessor(processingSystem);
|
||||
});
|
||||
|
||||
test('应该能够创建处理系统', () => {
|
||||
|
||||
Reference in New Issue
Block a user