nject

Crates.io version Download docs.rs docs


Simple zero cost dependency injection library made for rust

Install

Add the following to your Cargo.toml: toml [dependencies] nject = "0.3"

Why nject?

Use cases

Removes the need to specify dependencies across your modules

```rust use nject::{injectable, provider};

[injectable]

struct DepOne;

[injectable]

struct DepTwo { dep: DepOne, }

[injectable]

struct Facade { dep: DepTwo, }

[provider]

struct Provider;

fn main() { let _facade: Facade = Provider.provide(); }

```

Works with lifetimes - enables shared dependencies

```rust use nject::{injectable, provider};

struct DepOne;

[injectable]

struct Facade<'a> { dep: &'a DepOne, }

[provider]

struct Provider<'a> { #[provide] shared: &'a DepOne, }

fn main() { let provider = Provider { shared: &DepOne }; let _facade: Facade = provider.provide(); }

```

Works with dyn traits

```rust use nject::{injectable, provider};

trait Greeter { fn greet(&self); }

[injectable]

struct GreeterOne;

impl Greeter for GreeterOne { fn greet(&self) { println!("Greeting"); } }

[injectable]

struct Facade<'a> { boxeddep: Box, refdep: &'a dyn Greeter, }

[provider]

[provide(Box, Box::::new(self.provide()))]

struct Provider { #[provide(dyn Greeter)] greeter: GreeterOne, }

fn main() { let provider = Provider { greeter: GreeterOne }; let _facade: Facade = provider.provide(); }

```

Works with generics

```rust use nject::{injectable, provider};

[injectable]

struct DepOne;

[injectable]

struct Facade { dep: T, }

[provider]

struct Provider;

fn main() { let _facade: Facade = Provider.provide(); }

```

Works with generic providers

```rust use nject::{injectable, provider};

trait Greeter { fn greet(&self); }

[injectable]

struct DevGreeter;

impl Greeter for DevGreeter { fn greet(&self) { println!("Greeting Dev"); } }

[injectable]

struct ProdGreeter;

impl Greeter for ProdGreeter { fn greet(&self) { println!("Greeting production"); } }

[injectable]

struct Facade<'a> { dep: &'a dyn Greeter, }

[provider]

struct Provider<'a, T: Greeter>(#[provide(dyn Greeter)] &'a T);

fn main() { let devfacade: Facade = Provider(&DevGreeter).provide(); let prodfacade: Facade = Provider(&ProdGreeter).provide(); } ```

Easily inject non-injectable dependencies

```rust use nject::{inject, injectable, provider};

[inject(Self { noninjectablevalue: 123 })]

struct InjectableFromInjectAttr { noninjectablevalue: i32, }

struct NonInjectable { noninjectablevalue: i32, }

[inject(Self {

non_injectable_value: injectable_dep.non_injectable_value + 10, 
injectable_dep

}, injectabledep: InjectableFromInjectAttr)] struct PartiallyInjectable { noninjectablevalue: i32, injectabledep: InjectableFromInjectAttr }

[injectable]

struct Facade { depfrominjected: InjectableFromInjectAttr, depfrompartialinject: PartiallyInjectable, #[inject(NonInjectable { noninjectablevalue: 456 })] depfrominjectattr: NonInjectable, #[inject(InjectableFromInjectAttr { noninjectablevalue: 789 })] depfrominjectattroverride: InjectableFromInjectAttr, #[inject(PartiallyInjectable { noninjectablevalue: 111, injectabledep }, injectabledep: InjectableFromInjectAttr)] depfrompartialinjectattr_override: PartiallyInjectable, }

[provider]

struct Provider;

fn main() { let _facade = Provider.provide::(); } ```

Use modules to export internal shared dependencies

```rust use nject::{injectable, provider};

mod sub { use nject::{injectable, module};

#[injectable]
struct InternalType( #[inject(123)] i32); // Not visible outside of module.

#[injectable]
pub struct Facade<'a> {
    hidden: &'a InternalType
}

#[injectable]
#[module]
pub struct Module {
    #[export]
    hidden: InternalType
}

}

[injectable]

[provider]

struct Provider { #[import] subModule: sub::Module }

fn main() { #[provider] struct InitProvider;

let provider = InitProvider.provide::<Provider>();
let _facade = provider.provide::<sub::Facade>();

}

```

Limitations

  1. Dependencies can only be exported by a single module.
  2. Modules can only export types defined in its crate.
  3. Generic parameters are not supported on modules.

Examples

You can look into the axum example for a Web API use case or into the Leptos example for a Web App.

Credits