pub struct ContainerBuilder { /* private fields */ }Expand description
Builder for constructing a Container.
The builder supports:
- Registering dynamic providers for external types
- Setting a custom singleton store
- Startup validation
§Registering External Types
Use register to provide a closure-based
provider for types you don’t control:
let container = Container::builder()
// Simple: no dependencies
.register(DynProvider::new(|| {
Ok(reqwest::Client::new())
}))
// With context: depends on other injectables
.register(DynProvider::with_ctx(|ctx| async move {
let config = ctx.resolve::<AppConfig>().await?;
Ok(sqlx::SqlitePool::connect(&config.db_url).await?)
}))
.build()
.await?;Then resolve with Container::resolve_external:
let client: reqwest::Client = container.resolve_external().await?;Implementations§
Source§impl ContainerBuilder
impl ContainerBuilder
Sourcepub fn with_store(self, store: Arc<dyn SingletonStore>) -> Self
pub fn with_store(self, store: Arc<dyn SingletonStore>) -> Self
Set a custom singleton store for the container.
The store is typically auto-generated by the macro. Use this method only for custom store implementations.
Sourcepub fn register<T: Send + Sync + 'static>(
self,
token: impl Into<String>,
provider: DynProvider<T>,
) -> Self
pub fn register<T: Send + Sync + 'static>( self, token: impl Into<String>, provider: DynProvider<T>, ) -> Self
Register a dynamic provider for an external type under the given token.
Every registration is keyed by (TypeId<T>, token), so multiple providers
of the same type can coexist as long as they carry different tokens. Use
DEFAULT_TOKEN ("") for the
canonical, unnamed registration.
§Simple Registration (default token)
builder.register("", DynProvider::sync(|| Ok(reqwest::Client::new())));
// later:
let client = container.resolve_external::<reqwest::Client>().await?;§Multiple Providers of the Same Type
builder
.register("primary", DynProvider::new(|| async { Ok(primary_pool()) }))
.register("replica", DynProvider::new(|| async { Ok(replica_pool()) }));
// later:
let primary: Pool = container.resolve_external_with_token("primary").await?;
let replica: Pool = container.resolve_external_with_token("replica").await?;§Context-Aware Registration
builder.register("", DynProvider::with_ctx(|ctx| async move {
let config = ctx.extract::<Inject<AppConfig>>().await?;
Ok(Database::connect(&config.db_url).await?)
}));Sourcepub fn register_or_replace<T: Send + Sync + 'static>(
self,
token: impl Into<String>,
provider: DynProvider<T>,
) -> Self
pub fn register_or_replace<T: Send + Sync + 'static>( self, token: impl Into<String>, provider: DynProvider<T>, ) -> Self
Register a dynamic provider, silently replacing any existing provider
for the same (type, token) pair.
Use this in tests or layered-config scenarios where you intentionally want to override an existing registration.
Sourcepub async fn build(self) -> InjectableResult<Container>
pub async fn build(self) -> InjectableResult<Container>
Build the container.
This performs startup validation of the dependency graph (collected
automatically from all #[injectable] and #[injectable]
types via the inventory crate) and the singleton store, then
returns a ready-to-use container.
§Validation
The dependency graph is validated at build time for:
- Circular dependencies
- Scope mismatches (singleton depending on transient)
- Missing dependencies
- Duplicate registrations
If any validation errors are found, the build fails with
InjectableError::ConstructionFailed.