Crates.io | derive_di |
lib.rs | derive_di |
version | 0.3.0 |
source | src |
created_at | 2020-09-21 14:15:55.291164 |
updated_at | 2020-09-24 12:14:25.251218 |
description | This crate is realized the dependency injection pattern |
homepage | |
repository | https://github.com/Mnwa/derive_di |
max_upload_size | |
id | 291164 |
size | 28,252 |
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.
use derive_di::*;
#[injectable]
#[derive(Default)]
struct InjectableStruct;
#[derive(Container)]
struct MyContainer {
i_struct: InjectableStruct,
}
That code, which will be generated for you
use derive_di::*;
#[derive(Default)]
struct InjectableStruct;
impl Injectable for InjectableStruct {
fn get_service() -> Self {
Default::default()
}
}
struct MyContainer {
i_struct: InjectableStruct,
}
impl MyContainer {
pub fn get_i_struct(&self) -> &InjectableStruct {
&self.i_struct
}
pub fn get_i_struct_mut(&mut self) -> &mut InjectableStruct {
&mut self.i_struct
}
pub fn set_i_struct(&mut self, i_struct: InjectableStruct) {
self.i_struct = i_struct
}
}
impl Default for MyContainer {
fn default() -> Self {
Self {
i_struct: Injectable::get_service()
}
}
}
You can pass any factory to the injectable
macro for building you struct.
You can build you struct inside injectable
macro.
#[injectable(factory => InjectableStruct {inner: "test".to_owned()})]
struct InjectableStruct {
inner: String,
}
The Injectable
will be look like this
impl Injectable for InjectableStruct {
fn get_service() -> Self {
InjectableStruct {inner: "test".to_owned()}
}
}
You can build you struct inside injectable
macro with factory method.
fn factory_struct() -> InjectableStruct {
InjectableStruct {
inner: "test".to_owned(),
}
}
#[injectable(factory => factory_struct())]
struct InjectableStruct {
inner: String,
}
The Injectable
will be look like this
impl Injectable for InjectableStruct {
fn get_service() -> Self {
factory_struct()
}
}
You can build you struct inside injectable
macro with factory closure.
#[injectable(factory => || InjectableStruct {inner: "test".to_owned()})]
struct InjectableStruct {
inner: String,
}
The Injectable
will be look like this
impl Injectable for InjectableStruct {
fn get_service() -> Self {
(|| InjectableStruct {inner: "test".to_owned()})()
}
}
dyn Trait
container fieldsWith the inject
macro, you can easy to solve dyn Trait
fields in tou container.
#[injectable(factory => InjectableStruct)]
struct InjectableStruct;
trait Getter {
fn get(&self) -> String;
}
impl Getter for InjectableStruct {
fn get(&self) -> String {
"test".to_owned()
}
}
#[derive(Container)]
struct MyContainer {
#[inject(InjectableStruct)]
i_struct: Box<dyn Getter>,
}
The Default
impl of theMyContainer
will be looks like
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.
#[injectable(factory => || InjectableStruct)]
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()
}
}
#[derive(Container)]
struct MyContainer {
#[inject(InjectableStruct)]
i_struct: Box<dyn Getter>,
}
fn main() {
let mut container = MyContainer::default();
assert_eq!("test", container.get_i_struct().get());
container.set_i_struct(Box::from(GetterMock));
assert_eq!("mocked", container.get_i_struct().get())
}