Skip to main content

Container

Struct Container 

Source
pub struct Container { /* private fields */ }
Expand description

High-performance dependency injection container.

Uses lock-free data structures for maximum concurrent throughput. Supports hierarchical scopes with full parent chain resolution.

§Examples

use dependency_injector::Container;

#[derive(Clone)]
struct MyService { name: String }

let container = Container::new();
container.singleton(MyService { name: "test".into() });

let service = container.get::<MyService>().unwrap();
assert_eq!(service.name, "test");

Implementations§

Source§

impl Container

Source

pub fn new() -> Self

Create a new root container.

§Examples
use dependency_injector::Container;
let container = Container::new();
Source

pub fn with_capacity(capacity: usize) -> Self

Create a container with pre-allocated capacity.

Use this when you know approximately how many services will be registered.

Source

pub fn scope(&self) -> Self

Create a child scope that inherits from this container.

Child scopes can:

  • Access all services from parent scopes
  • Override parent services with local registrations
  • Have their own transient/scoped services
§Examples
use dependency_injector::Container;

#[derive(Clone)]
struct AppConfig { debug: bool }

#[derive(Clone)]
struct RequestId(String);

let root = Container::new();
root.singleton(AppConfig { debug: true });

let request = root.scope();
request.singleton(RequestId("req-123".into()));

// Request scope can access root config
assert!(request.contains::<AppConfig>());
Source

pub fn create_scope(&self) -> Self

Alias for scope() - creates a child container.

Source

pub fn singleton<T: Injectable>(&self, instance: T)

Register a singleton service (eager).

The instance is stored immediately and shared across all resolves.

§Examples
use dependency_injector::Container;

#[derive(Clone)]
struct Database { url: String }

let container = Container::new();
container.singleton(Database { url: "postgres://localhost".into() });
Source

pub fn lazy<T: Injectable, F>(&self, factory: F)
where F: Fn() -> T + Send + Sync + 'static,

Register a lazy singleton service.

The factory is called once on first access, then the instance is cached.

§Examples
use dependency_injector::Container;

#[derive(Clone)]
struct ExpensiveService { data: Vec<u8> }

let container = Container::new();
container.lazy(|| ExpensiveService {
    data: vec![0; 1024 * 1024], // Only allocated on first use
});
Source

pub fn transient<T: Injectable, F>(&self, factory: F)
where F: Fn() -> T + Send + Sync + 'static,

Register a transient service.

A new instance is created on every resolve.

§Examples
use dependency_injector::Container;
use std::sync::atomic::{AtomicU64, Ordering};

static COUNTER: AtomicU64 = AtomicU64::new(0);

#[derive(Clone)]
struct RequestId(u64);

let container = Container::new();
container.transient(|| RequestId(COUNTER.fetch_add(1, Ordering::SeqCst)));

let id1 = container.get::<RequestId>().unwrap();
let id2 = container.get::<RequestId>().unwrap();
assert_ne!(id1.0, id2.0); // Different instances
Source

pub fn register_factory<T: Injectable, F>(&self, factory: F)
where F: Fn() -> T + Send + Sync + 'static,

Register using a factory (alias for lazy).

Source

pub fn register<T: Injectable>(&self, instance: T)

Register an instance (alias for singleton).

Source

pub fn register_boxed<T: Injectable>(&self, instance: Box<T>)

Register a boxed instance.

Source

pub fn register_by_id( &self, type_id: TypeId, instance: Arc<dyn Any + Send + Sync>, )

Register by TypeId directly (advanced use).

Source

pub fn get<T: Injectable>(&self) -> Result<Arc<T>>

Resolve a service by type.

Returns Arc<T> for zero-copy sharing. Walks the parent chain if not found in the current scope.

§Performance

Uses thread-local caching for frequently accessed services (~8ns vs ~19ns). The cache is automatically populated on first access.

§Examples
use dependency_injector::Container;

#[derive(Clone)]
struct MyService;

let container = Container::new();
container.singleton(MyService);

let service = container.get::<MyService>().unwrap();
Source

pub fn clear_cache(&self)

Clear the thread-local hot cache.

The cache is automatically invalidated whenever this container is mutated (services registered, removed, or cleared), so calling this manually is rarely necessary. It remains available for explicit control, e.g. to release the cached Arcs held by the current thread.

Note: This clears the calling thread’s entire hot cache, including entries cached for other containers.

Source

pub fn warm_cache<T: Injectable>(&self)

Pre-warm the thread-local cache with a specific service type.

This can be useful at the start of request handling to ensure hot services are already in the cache.

§Example
use dependency_injector::Container;

#[derive(Clone)]
struct Database;

let container = Container::new();
container.singleton(Database);

// Pre-warm cache for hot services
container.warm_cache::<Database>();
Source

pub fn resolve<T: Injectable>(&self) -> Result<Arc<T>>

Alias for get - resolve a service.

Source

pub fn try_get<T: Injectable>(&self) -> Option<Arc<T>>

Try to resolve, returning None if not found.

§Examples
use dependency_injector::Container;

#[derive(Clone)]
struct OptionalService;

let container = Container::new();
assert!(container.try_get::<OptionalService>().is_none());
Source

pub fn try_resolve<T: Injectable>(&self) -> Option<Arc<T>>

Alias for try_get.

Source

pub fn contains<T: Injectable>(&self) -> bool

Check if a service is registered.

Checks both current scope and parent scopes.

Source

pub fn has<T: Injectable>(&self) -> bool

Alias for contains.

Source

pub fn len(&self) -> usize

Get the number of services in this scope (not including parents).

Source

pub fn is_empty(&self) -> bool

Check if this scope is empty.

Source

pub fn registered_types(&self) -> Vec<TypeId>

Get all registered TypeIds in this scope.

Source

pub fn depth(&self) -> u32

Get the scope depth (0 = root).

Source

pub fn debug_registrations(&self) -> String

Format a human-readable summary of every registration visible to this container, for logging when a resolution unexpectedly fails.

The summary lists the scope depth, the number of services registered in each scope of the parent chain, and the TypeId of every registration. The container stores services by TypeId only (type names are not retained), so pair this output with the type_name carried by DiError::NotFound when diagnosing a failed resolve.

§Examples
use dependency_injector::Container;

#[derive(Clone)]
struct MyService;

let root = Container::new();
root.singleton(MyService);

let scope = root.scope();
if scope.get::<String>().is_err() {
    eprintln!("{}", scope.debug_registrations());
}
Source

pub fn lock(&self)

Lock the container to prevent further registrations.

Useful for ensuring no services are registered after app initialization.

Source

pub fn is_locked(&self) -> bool

Check if the container is locked.

Source

pub fn clear(&self)

Clear all services from this scope.

Does not affect parent scopes.

Source

pub fn remove<T: Injectable>(&self) -> bool

Remove a service registration from this scope.

Returns true if a service of type T was registered in this scope and has been removed, false otherwise. Does not affect parent scopes. Like clear, removal is permitted on a locked container (locking prevents new registrations, not removal).

§Examples
use dependency_injector::Container;

#[derive(Clone)]
struct MyService;

let container = Container::new();
container.singleton(MyService);

assert!(container.remove::<MyService>());
assert!(!container.contains::<MyService>());
assert!(!container.remove::<MyService>()); // Already removed
Source

pub fn batch<F>(&self, f: F)
where F: FnOnce(BatchRegistrar<'_>),

Register multiple services in a single batch operation.

This is more efficient than individual registrations when registering many services at once, as it:

  • Performs a single lock check at the start
  • Minimizes per-call overhead
§Examples
use dependency_injector::Container;

#[derive(Clone)]
struct Database { url: String }
#[derive(Clone)]
struct Cache { size: usize }
#[derive(Clone)]
struct Logger { level: String }

let container = Container::new();
container.batch(|batch| {
    batch.singleton(Database { url: "postgres://localhost".into() });
    batch.singleton(Cache { size: 1024 });
    batch.singleton(Logger { level: "info".into() });
});

assert!(container.contains::<Database>());
assert!(container.contains::<Cache>());
assert!(container.contains::<Logger>());

Note: For maximum performance with many services, prefer the builder API:

use dependency_injector::Container;

#[derive(Clone)]
struct A;
#[derive(Clone)]
struct B;

let container = Container::new();
container.register_batch()
    .singleton(A)
    .singleton(B)
    .done();
Source

pub fn register_batch(&self) -> BatchBuilder<'_>

Start a fluent batch registration.

This is faster than the closure-based batch() for many services because it avoids closure overhead.

§Example
use dependency_injector::Container;

#[derive(Clone)]
struct Database { url: String }
#[derive(Clone)]
struct Cache { size: usize }

let container = Container::new();
container.register_batch()
    .singleton(Database { url: "postgres://localhost".into() })
    .singleton(Cache { size: 1024 })
    .done();

assert!(container.contains::<Database>());
assert!(container.contains::<Cache>());

Trait Implementations§

Source§

impl Clone for Container

Source§

fn clone(&self) -> Container

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Container

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Container

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Send for Container

Source§

impl ServiceProvider for Container

Source§

fn provide<T: Service>(&self)

Register a service using its Service implementation. Read more
Source§

fn provide_singleton<T: Service>(&self) -> bool

Register a service as a singleton with pre-resolved dependencies. Read more
Source§

fn provide_transient<T: Service>(&self)

Register a service as transient. Read more
Source§

impl Sync for Container

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<R, D> DepsPresent<D> for R

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Injectable for T
where T: Send + Sync + 'static,

Source§

fn type_id_of() -> TypeId
where Self: Sized,

Returns the TypeId of this type (for internal use)
Source§

fn type_name_of() -> &'static str
where Self: Sized,

Returns the type name for debugging
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Provider for T
where T: Injectable,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<R, D> VerifyDeps<D> for R

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more