Skip to main content

Dependency Management

The DependencyManager is a lightweight yet powerful dependency injection container integrated into the Spinorium engine. It lets you register and resolve implementations, control substitutions, and reuse instances via pooling.

Using the Dependency Manager

The dependency manager consists of two main classes: DependencyManager and DependencyGroup. The DependencyManager is the main class for managing dependencies, while DependencyGroup allows you to group related dependencies together. The dependency manager allows registering and resolving dependencies in three ways:

  1. Direct registration: Associate a target class with an implementation class.
  2. Name-based registration: Associate a name with an implementation class.
  3. Subtype registration: Associate a subtype of a target class with an implementation class.

An instance of the manager is accessible via System.dependency. You can predefine dependencies during engine initialization:

  • timelineExtensionsList:Array<Class> – A list of timeline extensions to be registered on engine startup. These extensions enhance or modify the behavior of the timeline system.
  • dependenciesList:Array<[Class, Class]> – A list of dependencies to be registered on engine startup. Each entry consists of a pair mapping a base class to its replacement class.
  • componentsList:Array<[string, Class]> – A list of components to be registered on engine startup. Each entry consists of a component type mapped to its class.

You can register new dependencies, resolve them, and allocate instances in real time. The dependency manager is accessible before the engine is initialized. This allows you to register low-level dependencies before the engine starts.

  • register(target, creator) – Registers a class constructor as the default implementation for a target type.
  • registerByName(name, creator) – Registers a class constructor with the specified name.
  • registerBySubtype(target, subtype, creator) – Registers a class constructor as a subtype of a target type.
  • resolve(target) – Resolves the actual class constructor for a target type. Returns the registered implementation if available, otherwise returns the target itself.
  • resolveByName(name) – Resolves a class constructor by its registered name.
  • resolveBySubtype(target, subtype) – Resolves a class constructor by its registered subtype.
  • allocate(target, ...params) – Creates a new instance of a class or returns a cached instance if available. Uses object pooling to reuse instances when possible.
  • allocateByName(name, ...params) – Creates a new instance of a class registered by name.
  • allocateBySubtype(target, subtype, ...params) – Creates a new instance of a class registered as a subtype.
  • release(instance) – Returns an instance to the object pool for later reuse. The instance will be available for future allocations.

Configuration Example

class GameSymbolView extends SymbolView {
// Custom implementation
}

class CustomPanel extends Container {
// Components, created in the editor
private readonly _background:SpineAnimation;
private readonly _balanceTxt:TextField;
private readonly _currentBetTxt:TextField;
private readonly _spinBtn:Button;

// Custom implementation
}

System.initialize({
dependencyManager: {
dependenciesList: [
// Replace the default SymbolView with a custom implementation
[ SymbolView, GameSymbolView ]
],
componentsList: [
// Register a custom panel component
[ 'CustomPanel', CustomPanel ]
]
}
});

Usage Example

class CustomSprite extends Sprite {
// Custom implementation
}

System.dependency.register(Sprite, CustomSprite);
const sprite = System.dependency.allocate(Sprite);

// Outputs "true" in the console
console.log(sprite instanceof CustomSprite);

Using Dependency Groups

Dependency groups allow you to group related dependencies together, making it easier to manage and resolve them. It's mostly designed for internal use. The DependencyGroup does not perform pooling — allocate() always constructs a new instance. You can create a dependency group and register dependencies within it.

  • register(name, creator) – Registers a dependency by name.
  • resolve(name) – Resolves a dependency by name.
  • allocate(name, ...params) – Allocates an instance of a dependency by name.

The System.dependency also exposes predefined groups you can use:

  • animationsDependencyGroup for animation players keyed by AnimationType.
  • fetchersDependencyGroup for resource fetchers.
  • subcomponentsDependencyGroup for low-level display objects used by components.
  • componentsDependencyGroup for component linkages created by the editor.

Usage Example

// Create a dependency group
const animations = new DependencyGroup();

// Register dependencies in the group
animations.register(AnimationType.MOVIE_CLIP, MovieClipAnimation);
animations.register(AnimationType.SPINE, SpineAnimation);
animations.register(AnimationType.PARTICLES, ParticlesAnimation);

// Resolve a dependency from the group
const animation = animations.allocate(AnimationType.SPINE);

// Outputs "true" in the console
console.log(animation instanceof SpineAnimation);