Rust macro to automatically implement the dependency injection pattern for arbitrary structs.
A simple #[derive(Container)]
will generate new getters and setters for every field of your struct.
Also, the Container will implement the Default
trait, where will inject every field with Injectable
trait.
```rust use derive_di::*;
struct InjectableStruct;
struct MyContainer { i_struct: InjectableStruct, } ```
That code, which will be generated for you
```rust use derive_di::*;
struct InjectableStruct; impl Injectable for InjectableStruct { fn get_service() -> Self { Default::default() } }
struct MyContainer { i_struct: InjectableStruct, }
impl MyContainer { pub fn getistruct(&self) -> &InjectableStruct { &self.istruct } pub fn getmutistruct(&mut self) -> &mut InjectableStruct { &mut self.istruct } pub fn setistruct(&mut self, istruct: InjectableStruct) { self.istruct = istruct } }
impl Default for MyContainer { fn default() -> Self { Self { istruct: Injectable::getservice() } } } ```
You can pass any factory to the injectable
macro for building you struct.
You can build you struct inside injectable
macro.
```rust
struct InjectableStruct {
inner: String,
}
The `Injectable` will be look like this
rust
impl Injectable for InjectableStruct {
fn getservice() -> Self {
InjectableStruct {inner: "test".toowned()}
}
}
```
You can build you struct inside injectable
macro with factory method.
```rust
fn factorystruct() -> InjectableStruct {
InjectableStruct {
inner: "test".toowned(),
}
}
struct InjectableStruct {
inner: String,
}
The `Injectable` will be look like this
rust
impl Injectable for InjectableStruct {
fn getservice() -> Self {
factorystruct()
}
}
```
You can build you struct inside injectable
macro with factory closure.
```rust
struct InjectableStruct {
inner: String,
}
The `Injectable` will be look like this
rust
impl Injectable for InjectableStruct {
fn getservice() -> Self {
(|| InjectableStruct {inner: "test".toowned()})()
}
}
```
dyn Trait
container fieldsWith the inject
macro, you can easy to solve dyn Trait
fields in tou container.
```rust
struct InjectableStruct;
trait Getter { fn get(&self) -> String; }
impl Getter for InjectableStruct { fn get(&self) -> String { "test".to_owned() } }
struct MyContainer {
#[inject(InjectableStruct)]
i_struct: Box
The
Defaultimpl of the
MyContainer` will be looks like
rust
impl Default for MyContainer {
fn default() -> Self {
Self {
i_struct: Box::from(InjectableStruct::get_service())
}
}
}
You can combine the dyn Trait
fields and setters in your container
and mock any logic for simple testing.
```rust
struct InjectableStruct;
trait Getter { fn get(&self) -> String; }
impl Getter for InjectableStruct { fn get(&self) -> String { "test".to_owned() } }
struct GetterMock; impl Getter for GetterMock { fn get(&self) -> String { "mocked".to_owned() } }
struct MyContainer {
#[inject(InjectableStruct)]
i_struct: Box
fn main() {
let mut container = MyContainer::default();
asserteq!("test", container.getistruct().get());
container.setistruct(Box::from(GetterMock));
asserteq!("mocked", container.getistruct().get())
}
```