2个不稳定版本
0.2.0 | 2021年11月25日 |
---|---|
0.1.0 | 2021年1月5日 |
#23 in #通过
每月140次下载
在 teloc 中使用
19KB
438 行
teloc
Teloc是一个简单的Rust编译时依赖注入框架,灵感来源于C#依赖注入框架。
什么是依赖注入(DI)?
依赖注入(DI)是一种对象接收它所依赖的其他对象的技术。这些其他对象被称为依赖。在典型的“使用”关系中,接收对象被称为客户端,传递(即“注入”)的对象被称为服务。传递服务给客户端的代码可以是许多种类,称为注入器。客户端不是指定它将使用哪个服务,而是注入器告诉客户端使用哪个服务。“注入”指的是将依赖(服务)传递给将使用它的对象(客户端)。
亮点
- 编译时 - teloc使用强大的Rust类型系统在编译时检查具有正确生命周期的依赖项的存在。这意味着如果所需的依赖项未注册或其生命周期比请求的短,则无法编译您的代码。如果您的代码可以编译,则意味着它可以运行!
- 无开销 - teloc仅使用无开销抽象,如特性和泛型、新类型和单元类型,以及编译时依赖项解析,因此您无需担心运行时的开销。
- 简单的API - teloc为您提供了一个简单的API,只需要一个结构和一个属性宏即可与库一起使用。
- 与现有环境的集成 - teloc可以与任何现有的框架(如actix-web、warp、rocket)一起使用。目前仅支持actix-web,如您在示例中看到的。
如何使用
存在一种类型可以作为服务提供者:ServiceProvider
。它用作存储具有 Instance
和 Singleton
生命周期的依赖项,并用于声明所有依赖项,使用 .add_*()
方法。它可以被分支以创建具有本地实例的本地作用域。
依赖项有四种生命周期
Transient
。服务在解析时创建。可以依赖于任何生命周期的依赖项。Singleton
。服务在ServiceProvider
中解析(懒加载)时创建一次。可以依赖于任何生命周期的依赖项。不能依赖于来自分支的ServiceProvider
实例的服务。Instance
。依赖项是在ServiceProvider
外部创建的,可以由任何其他依赖项使用。
工作原理
- 声明您的结构。
- 创建构造函数,并在其上添加
#[inject]
宏。 - 创建一个
ServiceProvider
对象。 - 使用
ServiceProvider::add_*
方法添加您的服务和依赖项。 - 如果需要创建本地作用域,请分支
ServiceProvider
。 - 使用
.resolve()
方法从提供者获取服务。 - 使用服务进行工作。
示例
use teloc::*;
// Declare your structs
struct ConstService {
number: i32,
}
// #[inject] macro is indicate that dependency can be constructed using this function
#[inject]
impl ConstService {
pub fn new(number: i32) -> Self {
ConstService { number }
}
}
// Derive macro can be used when all fields implement `Dependency` trait, but
// we recommend using the #[inject] macro it in production code instead.
#[derive(Dependency)]
struct Controller {
number_service: ConstService,
}
fn main() {
// Create `ServiceProvider` struct that store itself all dependencies
let sp = ServiceProvider::new()
// Add dependency with `Singleton` lifetime. More about lifetimes see above.
.add_singleton::<ConstService>()
// Add dependency with `Transient` lifetime. More about lifetimes see above.
.add_transient::<Controller>();
// Fork `ServiceProvider`. It creates a new `ServiceProvider` which will have
// access to the dependencies from parent `ServiceProvider`.
let scope = sp
// .fork() method creates a local mutable scope with self parent immutable `ServiceProvider`.
.fork()
// Add an instance of `i32` that will be used when `ConstService` will be initialized.
.add_instance(10);
// Get dependency from `ServiceProvider`
let controller: Controller = scope.resolve();
assert_eq!(controller.number_service.number, 10);
}
有关文档,请参阅 docs.rs 上的页面。
与其他依赖注入框架的比较
功能 | teloc | shaku | waiter_di |
编译时检查 | 是 | 是 | 是 |
可以不使用 dyn 特性使用 | 是 | 是 | 是 |
一个应用程序中有许多服务提供者 | 是 | 是 | 否 |
不同的生命周期 | 是 | 是 | 否 |
如何读取错误
有时 teloc
可能会给出奇怪的巨大错误。但别担心!您可以定义您的问题,通过阅读阅读错误的手册。
专业技巧
本节包含您在处理库时可能想要使用的专业技巧。
获取 ServiceProvider
实例的类型
当您想要在结构中存储 ServiceProvider
的实例、从函数返回或作为参数传递时,这非常有用。
您需要什么
- 在
ServiceProvider
初始化后粘贴以下代码:let () = service_provider;
。 - 编译器将给出一个非常大的可怕类型,从
teloc::ServiceProvider<...>
开始。 - 将此类型复制到类型别名中,例如
type ConcreteSP = /*编译器输出*/;
。 - 当您想要编写
ServiceProvider
实例类型时,请使用ConcreteSP
。 - 如果您更改了
ServiceProvider
的初始化,请重复步骤 1-4。
许可证
根据您的选择,许可证为 Apache License, Version 2.0 或 MIT 许可证。除非您明确表示,否则根据 Apache-2.0 许可证定义,您有意提交以包含在此项目中的任何贡献,将按上述方式双重许可,不附加任何其他条款或条件。
依赖关系
约 2MB
约 44K SLoC