dill 0.5.0

Runtime depenency injection library.
Documentation

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)