Inversion is a dependency injection (IoC) container for Vala that provides inversion of control through component registration, lifecycle management, and field injection. It supports transient, scoped, and singleton lifecycles with a fluent registration API.
The central registry for component registrations. Holds singleton instances and creates scopes for scoped resolution.
Manages scoped instance lifetime. Created from a container and maintains its own cache of scoped instances.
Represents a component registration with implementation type, service aliases, lifecycle, and factory.
Enum defining instance lifetime: TRANSIENT, SCOPED, SINGLETON.
Interface for creating instances. Implementations: DelegateFactory, InstanceFactory.
using Inversion;
// Define service interface and implementation
public interface Logger : Object {
public abstract void log(string message);
}
public class ConsoleLogger : Object, Logger {
public void log(string message) {
stdout.printf("[LOG] %s\n", message);
}
}
// Create container and register
var container = new Container();
container.register_singleton<ConsoleLogger>((scope) => new ConsoleLogger())
.as_type(typeof(Logger));
// Resolve via scope
var scope = container.create_scope();
var logger = scope.resolve<Logger>();
logger.log("Hello!");
// Register with factory delegate
container.register_singleton<MyService>((scope) => new MyService());
// Register as interface
container.register_singleton<MyImplementation>((scope) => new MyImplementation())
.as_type(typeof(IMyService));
container.register<MyImplementation>((scope) => new MyImplementation())
.as_type(typeof(IServiceA))
.as_type(typeof(IServiceB))
.with_lifecycle(Lifecycle.SCOPED);
container.register_singleton<FileLogger>((s) => new FileLogger())
.as_type(typeof(Logger));
container.register_singleton<ConsoleLogger>((s) => new ConsoleLogger())
.as_type(typeof(Logger));
// Resolve all implementations
var all_loggers = scope.resolve_all<Logger>();
Dependencies can be injected via field initializers using inject<T>():
public class UserService : Object {
private Logger logger = inject<Logger>();
private Lot<IHandler> handlers = inject_all<IHandler>();
public void greet(string name) {
this.logger.log(@"Hello, $name!");
}
}
The injection context is automatically established during container resolution. Field initializers execute within the active scope, allowing dependencies to be resolved.
NOT_REGISTERED: Requested type not registeredCYCLE_DETECTED: Circular dependency foundILLEGAL_LIFECYCLE_COMBINATION: Invalid lifecycle for scope context
try {
var service = scope.resolve<IMyService>();
} catch (ContainerError.NOT_REGISTERED e) {
// Handle missing registration
} catch (ContainerError.CYCLE_DETECTED e) {
// Handle circular dependency
} catch (Error e) {
// Handle other errors
}
Inversion is a Vala IoC container providing dependency injection through component registration with transient, scoped, and singleton lifecycles, field injection via inject<T>(), multi-registration support, and scope-local registrations.