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 日 |
#373 在 Rust 模式
94 每月下载量
在 syrette_macros 中使用
190KB
4K SLoC
Syrette
Syrette 是一个方便的 Rust 依赖注入与反转控制框架。
同名的
来自 Syrette 维基百科文章。
注射器是一种通过针头注入液体的装置。它类似于注射器,但有一个封闭的柔性管(类似于通常用于牙膏的管子),而不是刚性管和活塞。
功能
- 依赖注入和反转控制容器
- 自动绑定依赖项
- API 启发于 InversifyJS
- 有用的错误信息
- 支持泛型实现和泛型接口特质
- 绑定单例
- 注入第三方结构和特质
- 命名绑定
- 异步工厂
可选特性
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 夜间版本的所有功能(例如 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。
待办事项
- 添加对泛型工厂的支持
贡献
您可以通过加入邮件列表来联系。
这是提交补丁、功能请求和报告错误的地方。
依赖项
~1.8–2.5MB
~53K SLoC