The App Container
TheApp struct is the central facade for dependency injection in Kit. It provides static methods for registering and resolving services throughout your application.
Registering Services
Singletons
Singletons are shared instances that persist for the application’s lifetime. The same instance is returned every time you resolve the type:Factories
Factories create a new instance every time the service is resolved:Trait Bindings
Bind a trait to a concrete implementation, enabling interface-based programming:Factory Trait Bindings
Create a new implementation instance each time the trait is resolved:Resolving Services
Basic Resolution
UseApp::get() for optional resolution or App::resolve() for required dependencies:
Trait Resolution
UseApp::make() or App::resolve_make() for trait objects:
Resolution in Controllers
The? operator makes dependency resolution clean and ergonomic in controllers:
The #[injectable] Macro
The #[injectable] macro provides automatic dependency injection with zero boilerplate. It:
- Automatically derives
Clone(andDefaultfor simple structs) - Registers the type as a singleton at application startup
- Resolves
#[inject]field dependencies automatically
Simple Injectable
For structs without dependencies:Injectable with Dependencies
Use#[inject] to mark fields that should be resolved from the container:
Unit Structs
Unit structs are also supported:Registration Methods
| Method | Description | Usage |
|---|---|---|
App::singleton(instance) | Register shared instance | App::singleton(MyService::new()) |
App::factory(closure) | Register factory for new instances | App::factory(|| MyService::new()) |
App::bind::<T>(arc) | Bind trait to implementation | App::bind::<dyn Trait>(Arc::new(impl)) |
App::bind_factory::<T>(closure) | Bind trait to factory | App::bind_factory::<dyn Trait>(|| Arc::new(impl)) |
Resolution Methods
| Method | Returns | Error Handling |
|---|---|---|
App::get::<T>() | Option<T> | Returns None if not found |
App::resolve::<T>() | Result<T, FrameworkError> | Returns error if not found |
App::make::<dyn T>() | Option<Arc<T>> | Returns None if not found |
App::resolve_make::<dyn T>() | Result<Arc<T>, FrameworkError> | Returns error if not found |
Checking Registration
Check if a service is registered before resolving:Convenience Macros
Kit provides macros for cleaner registration syntax:Testing with the Container
Kit providesTestContainer for isolated testing with fake implementations:
TestContainer Methods
| Method | Description |
|---|---|
TestContainer::fake() | Create isolated test container, returns guard |
TestContainer::singleton(instance) | Register fake singleton |
TestContainer::factory(closure) | Register fake factory |
TestContainer::bind::<T>(arc) | Bind fake trait implementation |
TestContainer::bind_factory::<T>(closure) | Bind fake trait factory |
TestContainerGuard ensures test isolation by automatically cleaning up when dropped.
Manual Registration in Bootstrap
While#[injectable] provides automatic registration, you may need to manually register services that require runtime configuration (like database connections, external API clients, or services configured from environment variables).
The bootstrap.rs file is the central location for manual service registration:
bootstrap::register() function is called from main.rs before the server starts:
For more details on the bootstrap file and when to use manual vs automatic registration, see the Bootstrap documentation.
Auto-Registration
Kit uses theinventory crate for compile-time service registration. Services marked with #[injectable] are automatically registered when App::boot_services() is called (this happens automatically in Server::from_config()).
Practical Examples
Service with Database Access
Service with Injected Dependencies
Using in Controller
Summary
| Feature | Usage |
|---|---|
| Register singleton | App::singleton(instance) or singleton!(instance) |
| Register factory | App::factory(closure) or factory!(closure) |
| Bind trait | App::bind::<dyn T>(arc) or bind!(dyn T, impl) |
| Resolve concrete | App::resolve::<T>()? |
| Resolve trait | App::resolve_make::<dyn T>()? |
| Auto-register | #[injectable] on struct |
| Inject dependency | #[inject] on field |
| Test faking | TestContainer::fake() |