4 个版本
0.3.0 | 2020 年 9 月 24 日 |
---|---|
0.2.2 | 2020 年 9 月 21 日 |
0.2.1 | 2020 年 9 月 21 日 |
0.2.0 | 2020 年 9 月 21 日 |
#1876 in Rust 模式
74 每月下载量
23KB
159 行
依赖注入模式 derive
Rust 宏,可自动为任意结构体实现依赖注入模式。简单的 #[derive(Container)]
将为你的结构体的每个字段生成新的获取器和设置器。此外,Container 将实现 Default
特性,其中将使用 Injectable
特性注入每个字段。
简单示例
use derive_di::*;
#[injectable]
#[derive(Default)]
struct InjectableStruct;
#[derive(Container)]
struct MyContainer {
i_struct: InjectableStruct,
}
为你生成的代码
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()
}
}
}
附加功能
工厂
你可以将任何工厂传递给 injectable
宏以构建你的结构体。
工厂结构体
你可以在 injectable
宏内部构建你的结构体。
#[injectable(factory => InjectableStruct {inner: "test".to_owned()})]
struct InjectableStruct {
inner: String,
}
Injectable
将看起来像这样
impl Injectable for InjectableStruct {
fn get_service() -> Self {
InjectableStruct {inner: "test".to_owned()}
}
}
工厂函数
你可以在 injectable
宏内部使用工厂方法构建你的结构体。
fn factory_struct() -> InjectableStruct {
InjectableStruct {
inner: "test".to_owned(),
}
}
#[injectable(factory => factory_struct())]
struct InjectableStruct {
inner: String,
}
Injectable
将看起来像这样
impl Injectable for InjectableStruct {
fn get_service() -> Self {
factory_struct()
}
}
工厂闭包
你可以在 injectable
宏内部使用工厂闭包构建你的结构体。
#[injectable(factory => || InjectableStruct {inner: "test".to_owned()})]
struct InjectableStruct {
inner: String,
}
Injectable
将看起来像这样
impl Injectable for InjectableStruct {
fn get_service() -> Self {
(|| InjectableStruct {inner: "test".to_owned()})()
}
}
自动将结构体注入到 dyn Trait
容器字段
使用 inject
宏,你可以轻松解决容器中的 dyn Trait
字段。
#[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>,
}
MyContainer
的 Default
实现将看起来像这样
impl Default for MyContainer {
fn default() -> Self {
Self {
i_struct: Box::from(InjectableStruct::get_service())
}
}
}
模拟
你可以在容器中组合 dyn Trait
字段和设置器,并为简单测试模拟任何逻辑。
#[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())
}
依赖关系
~1.5MB
~33K SLoC