#di #dependency #injection

nightly dill

Runtime depenency injection library

5 releases (breaking)

new 0.5.0 Mar 19, 2023
0.4.0 Mar 19, 2023
0.3.0 Jan 25, 2022
0.2.0 Jul 17, 2021
0.1.0 Jul 9, 2021

#86 in Configuration

Download history 39/week @ 2022-12-04 1/week @ 2022-12-11 12/week @ 2022-12-18 56/week @ 2022-12-25 23/week @ 2023-01-01 26/week @ 2023-01-08 30/week @ 2023-01-15 23/week @ 2023-01-22 44/week @ 2023-01-29 106/week @ 2023-02-05 37/week @ 2023-02-12 41/week @ 2023-02-19 3/week @ 2023-02-26 56/week @ 2023-03-05 123/week @ 2023-03-12

226 downloads per month

MIT/Apache

27KB
499 lines

dill

Runtime dependency injection library for Rust

Crates.io CI Dependencies

Example

/////////////////////////////////////////

// Define interfaces in traits
trait A: Send + Sync {
    fn test(&self) -> String;
}

// Implement traits to define components
#[component]
struct AImpl {
    // Auto-inject dependencies (also supports by-value)
    b: Arc<dyn B>,
}

impl A for AImpl {
    fn test(&self) -> String {
        format!("aimpl::{}", self.b.test())
    }
}

/////////////////////////////////////////

trait B: Send + Sync {
    fn test(&self) -> String;
}

#[component]
struct BImpl;

impl B for BImpl {
    fn test(&self) -> String {
        "bimpl".to_owned()
    }
}

/////////////////////////////////////////

// Register interfaces and bind them to implementations
let cat = CatalogBuilder::new()
    .add::<AImpl>()
    .bind::<dyn A, AImpl>()
    .add::<BImpl>()
    .bind::<dyn B, BImpl>()
    .build();

// Get objects and have their deps satisfied automatically
let inst = cat.get::<OneOf<dyn A>>().unwrap();
assert_eq!(inst.test(), "aimpl::bimpl");

TODO

Done

  • multiple implementations per interface
  • implementation-controlled sharing and lifetime
  • dependency specs
    • OneOf
    • AllOf
  • scopes
    • transient
    • singleton
  • auto builders
    • support scope in derivation
  • support prebuilt / add by value
  • support Impl::new()
  • argument bindings
  • by value injection of Clone types
  • Separate catalog use from catalog building
  • Make Catalog cloning cheap
  • Catalog self-injection

Principles

  • Nothing framework-specific

  • Create instance (ctor, new(), and external types)

  • Provide dynamic dependencies -> recurse

  • Provide fixed dependencies (Fn multi)

  • Get existing instance if exists (scope)

  • Separate builder from the scope, catalog, Arc stuff

  • Pass build context instead of catalog (e.g. for stack tracking)

Dependencies

~0.7–1.1MB
~27K SLoC