19 个稳定版本
1.6.6 | 2024年2月13日 |
---|---|
1.6.5 | 2021年4月25日 |
1.6.4 | 2020年11月25日 |
1.6.1 | 2020年10月28日 |
1.2.1 | 2020年8月29日 |
#1350 in 开发工具
64 每月下载量
在 waiter_di 中使用
40KB
861 行
Rust 的依赖注入
如何使用
Cargo.toml
:
waiter_di = "1.6.5"
lib.rs
或任何其他使用库的文件
use waiter_di::*;
查看 examples/1_get_started.rs 以获取使用示例。
查看 examples/2_modules.rs 以获取带有模块和构造函数的示例。
查看 examples/3_inject_options_list.rs 以查看所有可用的注入选项的演示。
如何使用
使用 #[component]
注释结构体
#[component]
struct Comp {}
使用 #[provides]
注释 impl 块
#[provides]
impl Interface for Comp {}
创建容器
fn main() {
let mut container = Container::<profiles::Default>::new();
}
获取依赖引用
fn main() {
let comp = Provider::<dyn Interface>::get(&mut container);
}
注入引用
对于 Rc
#[component]
struct Dependency;
#[component]
struct Comp {
dependency_rc: Rc<Dependency>
}
fn main() {
let mut container = Container::<profiles::Default>::new();
Provider::<Comp>::get(&mut container);
}
要使用 Arc
而不是 Rc
,您需要在 cargo 中添加 async
功能
waiter_di = { version = "...", features = [ "async" ] }
您还可以使用 waiter_di::Wrc
类型,它将根据 async
功能编译为 Rc
或 Arc
要创建新结构体而不是获取引用
#[component]
struct Comp {
dependency: Dependency,
dependency_box: Box<Dependency>
}
fn main() {
let mut container = Container::<profiles::Default>::new();
Provider::<Comp>::create(&mut container);
Provider::<Comp>::create_boxed(&mut container);
}
属性
它在底层使用 config
crate,例如它尝试在参数中作为 --float_prop <value>
查找 float_prop
,如果没有找到,它尝试在环境变量中查找,之后尝试 config/{profile}.toml
,之后 config/default.toml
#[derive(Debug, Deserialize)]
struct ConfigObject {
i32_prop: i32
}
#[component]
struct Comp {
config: Config,
#[prop("int")] int_prop: usize,
#[prop("int")] int_prop_opt: Option<usize>,
#[prop("int" = 42)] int_prop_with_default_value: usize,
float_prop: f32,
#[prop] config_object: ConfigObject
}
依赖循环
使用 Deferred 类型
#[component]
struct Comp {
dependency_def: Deferred<Dependency>,
dependency_def_rc: Deferred<Rc<Dependency>>,
dependency_def_box: Deferred<Box<Dependency>>
}
配置文件
您可以使用来自 `waiter_di::profile` 的预定义配置文件或创建自定义配置文件。
struct CustomProfile;
#[provides(profiles::Dev, CustomProfile)]
impl Interface for Comp {}
fn main() {
let mut container = Container::<profiles::Default>::new();
let mut container = Container::<profiles::Dev>::new();
let mut container = Container::<CustomProfile>::new();
}
从参数、环境变量或 config/default.toml
获取配置文件
只需定义名为 profile
的属性作为 --profile <profile>
参数、profile
环境变量或 profile
在 config/default.toml
中的属性,然后使用 inject!
宏
fn main() {
let comp = inject!(Comp: profiles::Default, profiles::Dev);
}
inject!
宏不能用于多个组件,因此建议与模块一起使用
#[module]
struct SomeModule {
component: Component
}
#[module]
struct RootModule {
some_module: SomeModule
}
fn main() {
let root_module = inject!(RootModule: profiles::Default, profiles::Dev);
}
在这种情况下,#[module]
是 #[component]
的同义词
工厂函数
如果不能使用 #[component]
注解,则使用工厂函数代替
#[provides]
fn create_dependency(bool_prop: bool) -> Dependency {
Dependency { prop: bool_prop }
}
将其用作构造函数,请在 impl 块上使用 #[component]
struct Comp();
#[component]
impl Comp {
#[provides]
fn new() -> Self {
Self()
}
}
工厂函数不支持 Deferred
参数。在其他情况下,它可以接受与 #[component]
相同的参数类型。
工厂函数不支持外部类型
#[provides] // won't compile
fn create_external_type_dependency() -> HashMap<i32, i32> {
HashMap::new()
}
因此,您需要创建 crate 本地包装器
struct Wrapper(HashMap<i32, i32>);
#[provides]
fn create_external_type_dependency() -> Wrapper {
Wrapper(HashMap::new())
}
为了方便起见,您可以使用 #[wrapper]
属性来自动实现 Deref
#[wrapper]
struct HashMap(std::collections::HashMap<i32, i32>);
#[provides]
fn create_external_type_dependency() -> HashMap {
return HashMap(std::collections::HashMap::<i32, i32>::new());
}
依赖关系
~3.5–4.5MB
~88K SLoC