# Lifecycle Enum ## Overview `Lifecycle` defines instance lifetime behavior for registered components. Four lifecycles are supported: transient (new instance per resolve), scoped (one instance per scope), singleton (one instance per container), and startup (eagerly initialized singletons). ## Namespace `Inversion` ## Enum Declaration ```vala public enum Lifecycle ``` ## Values ### `TRANSIENT` A new instance is created every time the component is requested. ```vala container.register_transient((s) => new MyService()); var scope = container.create_scope(); var a = scope.resolve(); // New instance var b = scope.resolve(); // Different instance // a != b ``` Use for: - Lightweight, stateless services - Objects with no shared state - Per-operation handlers ### `SCOPED` A single instance is created per scope. Within the same scope, the same instance is returned for each request. ```vala container.register_scoped((s) => new UserSession()); var scope1 = container.create_scope(); var scope2 = container.create_scope(); var a1 = scope1.resolve(); // Instance A var a2 = scope1.resolve(); // Same Instance A // a1 == a2 var b1 = scope2.resolve(); // Instance B (different) // a1 != b1 ``` Use for: - Per-request context (web applications) - Unit-of-work patterns - Transaction scopes ### `SINGLETON` A single instance is created for the lifetime of the container. The same instance is returned for all requests across all scopes. ```vala container.register_singleton((s) => new Configuration()); var scope1 = container.create_scope(); var scope2 = container.create_scope(); var a = scope1.resolve(); // Instance A var b = scope2.resolve(); // Same Instance A // a == b ``` Use for: - Application-wide configuration - Shared caches - Connection pools - Logging services ### `STARTUP` A single instance is created at container initialization time. The same instance is returned for all requests across all scopes. These instances are created eagerly when `initialise()` is called. ```vala container.register_startup((s) => new DatabaseConnection()); // After all registrations, initialize startup components container.initialise(); var scope1 = container.create_scope(); var scope2 = container.create_scope(); var a = scope1.resolve(); // Instance A (already created) var b = scope2.resolve(); // Same Instance A // a == b ``` Use for: - Database connections that must be established at startup - Background services that need to start immediately - Health-checkable components - Any singleton that should fail fast if instantiation fails ## Lifecycle Constraints ### Singleton/Startup Scope Cannot Resolve Scoped When resolving from a singleton or startup context, scoped registrations cannot be resolved: ```vala // This throws ILLEGAL_LIFECYCLE_COMBINATION // A singleton cannot depend on a scoped service public class SingletonService : Object { private ScopedService scoped = inject(); // Error at runtime! } container.register_singleton((s) => new SingletonService()); container.register_scoped((s) => new ScopedService()); var scope = container.create_scope(); scope.resolve(); // Throws! ``` ### Scope-Local Registrations Scope-local registrations cannot be singletons or startup: ```vala // Compile-time precondition failure scope.register_local((s) => new MyService(), Lifecycle.SINGLETON); // Error: requires (lifecycle != Lifecycle.SINGLETON && lifecycle != Lifecycle.STARTUP) ``` ## Registration Methods by Lifecycle | Method | Lifecycle | |--------|-----------| | `register_transient()` | TRANSIENT | | `register_scoped()` | SCOPED | | `register_singleton()` | SINGLETON | | `register_startup()` | STARTUP | | `register(..., lifecycle)` | Specified | ## Comparison Table | Lifecycle | Instance Count | Scope Behavior | Memory | Initialization | |-----------|---------------|----------------|--------|----------------| | TRANSIENT | Per resolve | New each time | Highest | On demand | | SCOPED | Per scope | Shared in scope | Medium | On demand | | SINGLETON | Per container | Shared globally | Lowest | On demand | | STARTUP | Per container | Shared globally | Lowest | Eager (initialise()) | ## Usage Examples ### Configuration Singleton ```vala public class AppConfig : Object { public string database_path { get; set; } } container.register_singleton((s) => { var config = new AppConfig(); config.database_path = "/data/app.db"; return config; }); ``` ### Startup Database Connection ```vala public class DatabaseConnection : Object { public DatabaseConnection() throws DatabaseError { // Connect to database - fails fast if connection unavailable } } container.register_startup((s) => new DatabaseConnection()); // Will throw if database connection fails, allowing early detection container.initialise(); ``` ### Request-Scoped Context ```vala public class RequestContext : Object { public string request_id { get; construct set; } public User? current_user { get; set; } } // In request handler void handle_request(Request req) { var scope = container.create_scope(); scope.register_local_scoped((s) => { var ctx = new RequestContext(); ctx.request_id = req.id; return ctx; }); var handler = scope.resolve(); handler.process(); } ``` ### Transient Handlers ```vala public interface IRequestHandler : Object { public abstract void handle(Request req); } container.register_transient((s) => new CreateUserHandler()) .as_type(typeof(IRequestHandler)); container.register_transient((s) => new DeleteUserHandler()) .as_type(typeof(IRequestHandler)); // Each resolution creates new handler instances var handlers = scope.resolve_all(); ``` --- The Lifecycle enum defines four instance lifetime behaviors: TRANSIENT for per-resolution instances, SCOPED for per-scope instances, SINGLETON for container-wide single instances, and STARTUP for eagerly-initialized singletons.