Rudi

Crates.io version docs.rs docs

Rudi - an out-of-the-box dependency injection framework for Rust.

```rust use rudi::{Context, Singleton, Transient};

// Register fn(cx) -> A { A } as the constructor for A

[derive(Debug)]

[Transient]

struct A;

[derive(Debug)]

struct B(A);

// Register fn(cx) -> B { B::new(cx.resolve::<A>()) } as the constructor for B

[Transient]

impl B { fn new(a: A) -> B { B(a) } }

// Register fn(cx) -> C { C::B(cx.resolve::<B>()) } as the constructor for C

[allow(dead_code)]

[Transient]

enum C { A(A),

#[di]
B(B),

}

// Register fn(cx) -> () { Run(cx.resolve::<B>()) } as the constructor for ()

[Singleton]

fn Run(b: B, c: C) { println!("{:?}", b); assert!(matches!(c, C::B(_))); }

fn main() { // Automatically register all types and functions with the #[Singleton] or #[Transient] attribute. let mut cx = Context::auto_register();

// Get an instance of `()` from the `Context`, which will call the `Run` function.
// This is equivalent to `cx.resolve::<()>();`
cx.resolve()

} ```

Features

More complex example

```rust use std::{fmt::Debug, rc::Rc};

use rudi::{Context, Singleton, Transient};

// Register async fn(cx) -> i32 { 42 } as the constructor for i32, // and specify the name of the instance of this i32 type as "number".

[Singleton(name = "number")]

async fn Number() -> i32 { 42 }

// Register async fn(cx) -> Foo { Foo { number: cx.resolve_with_name_async("number").await } } // as the constructor for Foo, and specify the name of the instance of this Foo type as "foo".

[derive(Debug, Clone)]

[Singleton(async, name = "foo")]

struct Foo { #[di(name = "number")] number: i32, }

[derive(Debug)]

struct Bar(Foo);

impl Bar { fn into_debug(self) -> Rc { Rc::new(self) } }

// Register async fn(cx) -> Bar { Bar::new(cx.resolve_with_name_async("foo").await).await } // as the constructor for Bar. // // Bind the implementation of the Debug trait and the trait object of the Debug trait, // it will register asycn fn(cx) -> Rc<dyn Debug> { Bar::into_debug(cx.resolve_async().await) } // as the constructor for Rc<dyn Debug>.

[Transient(binds = [Self::into_debug])]

impl Bar { async fn new(#[di(name = "foo")] f: Foo) -> Bar { Bar(f) } }

[Singleton]

async fn Run(bar: Bar, debug: Rc, #[di(name = "foo")] f: Foo) { println!("{:?}", bar); asserteq!(format!("{:?}", bar), format!("{:?}", debug)); asserteq!(format!("{:?}", bar.0.number), format!("{:?}", f.number)); }

[tokio::main]

async fn main() { let mut cx = Context::auto_register();

cx.resolve_async().await

} ```

More examples can be found in the examples and tests directories.

Credits

Contributing

Thanks for your help improving the project! We are so happy to have you!

License

Licensed under either of

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.