Dependency Injection
ECS Framework provides decorators to simplify dependency injection.
@Injectable Decorator
Section titled “@Injectable Decorator”Marks a class as injectable:
import { Injectable, IService } from '@esengine/ecs-framework';
@Injectable()class GameService implements IService { constructor() { console.log('GameService created'); }
dispose(): void { console.log('GameService disposed'); }}@InjectProperty Decorator
Section titled “@InjectProperty Decorator”Injects dependencies via property decorator. Injection occurs after constructor execution, before onInitialize() is called:
import { Injectable, InjectProperty, IService } from '@esengine/ecs-framework';
@Injectable()class PlayerService implements IService { @InjectProperty(DataService) private data!: DataService;
@InjectProperty(GameService) private game!: GameService;
dispose(): void { // Cleanup resources }}Usage in EntitySystem
Section titled “Usage in EntitySystem”@Injectable()class CombatSystem extends EntitySystem { @InjectProperty(TimeService) private timeService!: TimeService;
@InjectProperty(AudioService) private audio!: AudioService;
constructor() { super(Matcher.all(Health, Attack)); }
onInitialize(): void { // Properties are injected at this point console.log('Delta time:', this.timeService.getDeltaTime()); }
processEntity(entity: Entity): void { this.audio.playSound('attack'); }}Note: Use
!assertion when declaring properties (e.g.,private data!: DataService) to indicate the property will be injected before use.
Registering Injectable Services
Section titled “Registering Injectable Services”Use registerInjectable to automatically handle dependency injection:
import { registerInjectable } from '@esengine/ecs-framework';
// Register service (automatically resolves @InjectProperty dependencies)registerInjectable(Core.services, PlayerService);
// Property dependencies are automatically injected on resolutionconst player = Core.services.resolve(PlayerService);@Updatable Decorator
Section titled “@Updatable Decorator”Marks a service as updatable, making it automatically called each frame:
import { Injectable, Updatable, IService, IUpdatable } from '@esengine/ecs-framework';
@Injectable()@Updatable() // Default priority is 0class PhysicsService implements IService, IUpdatable { update(deltaTime?: number): void { // Update physics simulation each frame }
dispose(): void {}}
// Specify update priority (lower values execute first)@Injectable()@Updatable(10)class RenderService implements IService, IUpdatable { update(deltaTime?: number): void { // Render each frame }
dispose(): void {}}Services with @Updatable decorator are automatically called by Core:
function gameLoop(deltaTime: number) { Core.update(deltaTime); // Automatically updates all updatable services}Service Dependencies
Section titled “Service Dependencies”Recommended to use @InjectProperty for service dependencies:
@Injectable()class ConfigService implements IService { private config: any = {};
get(key: string) { return this.config[key]; }
dispose(): void { this.config = {}; }}
@Injectable()class NetworkService implements IService { @InjectProperty(ConfigService) private config!: ConfigService;
onInitialize(): void { // Use injected service in onInitialize const apiUrl = this.config.get('apiUrl'); }
dispose(): void {}}
// Register services (in dependency order)registerInjectable(Core.services, ConfigService);registerInjectable(Core.services, NetworkService);@Inject Constructor Decorator
Section titled “@Inject Constructor Decorator”// ⚠️ Not recommended: Constructor injection (may not work in Cocos/Laya)@Injectable()class NetworkService implements IService { constructor( @Inject(ConfigService) private config: ConfigService ) {}}
// ✅ Recommended: Property injection (compatible with all platforms)@Injectable()class NetworkService implements IService { @InjectProperty(ConfigService) private config!: ConfigService;
onInitialize(): void { // Use injected service here }}