container-macro
Uses container!{} macro for compile-time DI graph validation and container construction. Use when wanting compile-time circular dependency detection, explicit registration declarations, or strict DI s
SKILL.mdskills/container-macro/SKILL.md
GitHubcontainer! Macro
The container! macro provides compile-time dependency graph validation and emits compile_error!() for issues like circular dependencies, scope mismatches, and missing dependencies.
Basic usage
use injectable::prelude::*;
container! {
// Leaf type — singleton by default
Database,
// With explicit scope
Cache { scope: "transient" },
// With dependencies (registered elsewhere)
UserService { deps: [Database, Cache] },
}
Compile-time checks
The macro validates at compile time:
- Circular dependencies: detected via DFS with full cycle path
- Scope mismatches: singleton depending on transient is rejected
- Missing dependencies: unregistered dependencies are caught
- Duplicate registrations: duplicate type names are caught
When to use vs Container::builder()
| Approach | Use when |
|---|---|
Container::builder() |
Runtime construction, dynamic registration |
container! {} |
Compile-time validation, strict DI setup |
// Runtime approach (no compile-time validation)
let container = Container::builder()
.register(DynProvider::sync(|| Ok(HttpClient::new())))
.build()
.await?;
// Compile-time approach (validates graph at compile time)
container! {
Database,
HttpClient,
UserService { deps: [Database, HttpClient] },
}
With scopes
container! {
// Singleton (default)
Database,
// Transient — fresh instance each resolution
RequestId { scope: "transient" },
// Singleton depending on transient (REJECTED at compile time)
// UserService { deps: [RequestId] }, // ERROR: singleton depends on transient
}
Limitations
- The
container!macro validates the declared graph, not all injectable types - Types using
#[injectable]derive are auto-registered viainventoryand must still be validated - Use
Container::builder().build()for full validation including auto-registered types
For most cases, Container::builder().build() is sufficient as it also validates the full graph at startup time.