# Usage Examples ## Overview Practical examples demonstrating Inversion IoC container features including basic registration, lifecycle management, field injection, multi-registration, and scope-local registrations. ## Basic Registration and Resolution ```vala using Inversion; public interface ILogger : Object { public abstract void log(string message); } public class ConsoleLogger : Object, ILogger { public void log(string message) { stdout.printf("[LOG] %s\n", message); } } public static int main(string[] args) { var container = new Container(); // Register implementation as interface container.register_singleton((scope) => new ConsoleLogger()) .as_type(typeof(ILogger)); // Create scope and resolve var scope = container.create_scope(); var logger = scope.resolve(); logger.log("Hello, World!"); return 0; } ``` ## Lifecycle Patterns ### Singleton (Application-Wide) ```vala public class Configuration : Object { public string db_path { get; set; } } container.register_singleton((s) => { var config = new Configuration(); config.db_path = "/data/app.db"; return config; }); // Same instance across all scopes var scope1 = container.create_scope(); var scope2 = container.create_scope(); var config1 = scope1.resolve(); var config2 = scope2.resolve(); // config1 == config2 ``` ### Scoped (Per-Request) ```vala public class UserSession : Object { public string user_id { get; set; } } container.register_scoped((s) => new UserSession()); // Same instance within scope var scope = container.create_scope(); var session1 = scope.resolve(); var session2 = scope.resolve(); // session1 == session2 // Different instance in different scope var other_scope = container.create_scope(); var session3 = other_scope.resolve(); // session1 != session3 ``` ### Transient (Per-Resolution) ```vala public class RequestHandler : Object { public void handle(string request) { stdout.printf("Handling: %s\n", request); } } container.register_transient((s) => new RequestHandler()); var scope = container.create_scope(); var handler1 = scope.resolve(); var handler2 = scope.resolve(); // handler1 != handler2 ``` ## Field Injection ```vala public interface IRepository : Object { public abstract string get_data(); } public interface IHandler : Object { public abstract void handle(string request); } public class UserService : Object { // Dependencies injected during construction private IRepository repo = inject(); private IHandler handler = inject(); public void process() { var data = repo.get_data(); handler.handle(data); } } // Register dependencies container.register_singleton((s) => new MemoryRepository()) .as_type(typeof(IRepository)); container.register_singleton((s) => new ConsoleHandler()) .as_type(typeof(IHandler)); container.register_scoped((s) => new UserService()); // Resolve - dependencies injected automatically var scope = container.create_scope(); var service = scope.resolve(); service.process(); ``` ## Multiple Implementations ```vala public interface IValidator : Object { public abstract bool validate(Object obj); } public class EmailValidator : Object, IValidator { public bool validate(Object obj) { stdout.printf("Validating email...\n"); return true; } } public class PhoneValidator : Object, IValidator { public bool validate(Object obj) { stdout.printf("Validating phone...\n"); return true; } } // Register multiple implementations container.register_singleton((s) => new EmailValidator()) .as_type(typeof(IValidator)); container.register_singleton((s) => new PhoneValidator()) .as_type(typeof(IValidator)); // Resolve all implementations var scope = container.create_scope(); var validators = scope.resolve_all(); validators.iterate((obj) => { var validator = (IValidator) obj; validator.validate(data); }); ``` ## Inject All Pattern ```vala public class ValidationService : Object { // Inject all IValidator implementations private Lot validators = inject_all(); public bool validate_all(Object obj) { foreach (var validator in validators) { if (!validator.validate(obj)) { return false; } } return true; } } ``` ## Scope-Local Registrations ```vala public class RequestContext : Object { public string request_id { get; set; } public string path { get; set; } } // Container has application-wide services var container = new Container(); container.register_singleton((s) => new Database()); // Each request creates a scope with request-specific context void handle_request(string request_id, string path) { var scope = container.create_scope(); // Register request-specific context (only visible in this scope) scope.register_local_scoped((s) => { var ctx = new RequestContext(); ctx.request_id = request_id; ctx.path = path; return ctx; }); // Handlers can resolve RequestContext var handler = scope.resolve(); handler.process(); } ``` ## Custom Factory with Dependencies ```vala public class OrderService : Object { private IOrderRepository repo; private ILogger logger; public OrderService(IOrderRepository repo, ILogger logger) { this.repo = repo; this.logger = logger; } } container.register_scoped((scope) => { // Resolve dependencies from scope var repo = scope.resolve(); var logger = scope.resolve(); return new OrderService(repo, logger); }); ``` ## Multiple Interface Registration ```vala public interface IRepository : Object { public abstract Object? find(int id); } public interface ICache : Object { public abstract void cache(Object obj); } public class CachedRepository : Object, IRepository, ICache { public Object? find(int id) { return null; } public void cache(Object obj) { } } // Register as both interfaces container.register_singleton((s) => new CachedRepository()) .as_type(typeof(IRepository)) .as_type(typeof(ICache)); // Can resolve by either interface var scope = container.create_scope(); var repo = scope.resolve(); var cache = scope.resolve(); // Both point to same CachedRepository instance ``` ## Error Handling ```vala try { var service = scope.resolve(); service.do_work(); } catch (ContainerError.NOT_REGISTERED e) { stderr.printf("Service not registered: %s\n", e.message); } catch (ContainerError.CYCLE_DETECTED e) { stderr.printf("Circular dependency: %s\n", e.message); } catch (ContainerError.ILLEGAL_LIFECYCLE_COMBINATION e) { stderr.printf("Lifecycle error: %s\n", e.message); } catch (Error e) { stderr.printf("Error: %s\n", e.message); } ``` ## Web Application Pattern ```vala public class ApplicationController : Object { private static Container container; static construct { container = new Container(); // Application-wide services container.register_singleton((s) => new Database("app.db")); container.register_singleton((s) => new RedisCache()); // Per-request services container.register_scoped((s) => new UserSession()); container.register_transient((s) => new RequestHandler()); } public void handle_request(Request req, Response res) { var scope = container.create_scope(); // Register request context scope.register_local_scoped((s) => { return new RequestContext(req.id, req.path); }); try { var handler = scope.resolve(); handler.handle(req, res); } catch (Error e) { res.error(500, e.message); } } } ``` --- These examples demonstrate Inversion IoC patterns including basic registration, lifecycle management, field injection with inject(), multi-registration with resolve_all(), and scope-local registrations for per-request contexts.