10 个版本
0.5.1 | 2023 年 10 月 1 日 |
---|---|
0.5.0 | 2023 年 9 月 21 日 |
0.4.2 | 2022 年 11 月 28 日 |
0.4.1 | 2022 年 10 月 30 日 |
0.1.1 | 2022 年 7 月 22 日 |
#1011 在 过程宏
每月 125 次下载
在 2 个 crates 中使用 (通过 syrette)
130KB
3.5K SLoC
Syrette
Rust 的便捷依赖注入和反转控制框架。
命名来源
来自 Syrette 维基百科文章。
注射器是一种通过针头注入液体的装置。它类似于注射器,但有一个封闭的柔性管(类似于通常用于牙膏的管子)而不是刚性管和活塞。
特性
- 依赖注入和反转控制容器
- 自动绑定依赖项
- 灵感来源于 InversifyJS 的 API
- 有用的错误信息
- 支持泛型实现和泛型接口特质
- 绑定单例
- 注入第三方结构体和特质
- 命名绑定
- 异步工厂
可选功能
factory
. 绑定工厂(Rust 夜间版本所需)prevent-circular
. 循环依赖的检测和预防。 (默认启用)async
. 异步支持
要使用这些功能,您必须在 Cargo 中启用它。
为什么要反转控制和依赖注入?
实践 IoC 和 DI 的原因是编写模块化和松耦合的应用程序。
这是我们试图避免的
impl Foo
{
/// ❌ Bad. Foo knows the construction details of Bar.
pub fn new() -> Self
{
Self {
bar: Bar::new()
}
}
以下更好
impl Foo
/// ✅ Better. Foo is unaware of how Bar is constructed.
pub fn new(bar: Bar) -> Self
{
Self {
bar
}
}
}
但是,当您有一个具有许多依赖项的大型代码库及其依赖项时,这迟早会变得相当繁琐。因为您必须在某个地方指定依赖项
let foobar = Foobar::new(
Foo:new(
Woof::new(),
Meow::new()),
Bar::new(
Something::new(),
SomethingElse::new(),
SomethingMore::new()
)
)
这就是 Syrette 出现的原因。
动机
其他Rust的DI和IoC库要么是未维护的(例如di),要么过于复杂且需要Rust nightly版本才能使用所有功能(例如anthill-di),或者API很奇怪(例如teloc)。
Syrette的目标是成为一个简单、有用、方便且熟悉的DI和IoC库。
示例用法
use std::error::Error;
use syrette::injectable;
use syrette::DIContainer;
use syrette::ptr::TransientPtr;
trait IWeapon
{
fn deal_damage(&self, damage: i32);
}
struct Sword {}
#[injectable(IWeapon)]
impl Sword
{
fn new() -> Self
{
Self {}
}
}
impl IWeapon for Sword
{
fn deal_damage(&self, damage: i32)
{
println!("Sword dealt {} damage!", damage);
}
}
trait IWarrior
{
fn fight(&self);
}
struct Warrior
{
weapon: TransientPtr<dyn IWeapon>,
}
#[injectable(IWarrior)]
impl Warrior
{
fn new(weapon: TransientPtr<dyn IWeapon>) -> Self
{
Self { weapon }
}
}
impl IWarrior for Warrior
{
fn fight(&self)
{
self.weapon.deal_damage(30);
}
}
fn main() -> Result<(), Box<dyn Error>>
{
let mut di_container = DIContainer::new();
di_container.bind::<dyn IWeapon>().to::<Sword>()?;
di_container.bind::<dyn IWarrior>().to::<Warrior>()?;
let warrior = di_container.get::<dyn IWarrior>()?.transient()?;
warrior.fight();
println!("Warrior has fighted");
Ok(())
}
更多示例请参见示例文件夹。
术语
瞬态
一个类型或特质,对于所有者来说是唯一的。
单例
只有一个实例的类型。与瞬态相反。通常不鼓励使用。
接口
表示类型的类型或特质(如果是类型,则是自身)。
工厂
一个函数,用于创建特定类型或特质的实例。
默认工厂
一个不接受任何参数的函数,用于创建特定类型或特质的实例。
Rust版本要求
Syrette需要Rust >= 1.62.1才能运行。这主要是由于依赖于Linkme。
待办事项
- 添加对泛型工厂的支持
贡献
您可以通过加入邮件列表来联系我们。
这是提交补丁、功能请求和报告错误的地方。
lib.rs
:
为Syrette包提供的宏。
依赖项
~0.6–1.6MB
~31K SLoC