2个不稳定版本

0.2.0 2021年11月25日
0.1.0 2021年1月5日

#23 in #通过

Download history 16/week @ 2024-03-11 8/week @ 2024-03-18 7/week @ 2024-03-25 39/week @ 2024-04-01 4/week @ 2024-04-15 19/week @ 2024-04-22 2/week @ 2024-04-29 14/week @ 2024-05-06 4/week @ 2024-05-13 2/week @ 2024-05-20 14/week @ 2024-05-27 21/week @ 2024-06-03 4/week @ 2024-06-10 64/week @ 2024-06-17 49/week @ 2024-06-24

每月140次下载
teloc 中使用

MIT/Apache

19KB
438

teloc

Teloc是一个简单的Rust编译时依赖注入框架,灵感来源于C#依赖注入框架

什么是依赖注入(DI)?

链接到维基百科

依赖注入(DI)是一种对象接收它所依赖的其他对象的技术。这些其他对象被称为依赖。在典型的“使用”关系中,接收对象被称为客户端,传递(即“注入”)的对象被称为服务。传递服务给客户端的代码可以是许多种类,称为注入器。客户端不是指定它将使用哪个服务,而是注入器告诉客户端使用哪个服务。“注入”指的是将依赖(服务)传递给将使用它的对象(客户端)。

亮点

  • 编译时 - teloc使用强大的Rust类型系统在编译时检查具有正确生命周期的依赖项的存在。这意味着如果所需的依赖项未注册或其生命周期比请求的短,则无法编译您的代码。如果您的代码可以编译,则意味着它可以运行!
  • 无开销 - teloc仅使用无开销抽象,如特性和泛型、新类型和单元类型,以及编译时依赖项解析,因此您无需担心运行时的开销。
  • 简单的API - teloc为您提供了一个简单的API,只需要一个结构和一个属性宏即可与库一起使用。
  • 与现有环境的集成 - teloc可以与任何现有的框架(如actix-web、warp、rocket)一起使用。目前仅支持actix-web,如您在示例中看到的。

如何使用

存在一种类型可以作为服务提供者:ServiceProvider。它用作存储具有 InstanceSingleton 生命周期的依赖项,并用于声明所有依赖项,使用 .add_*() 方法。它可以被分支以创建具有本地实例的本地作用域。

依赖项有四种生命周期

  1. Transient。服务在解析时创建。可以依赖于任何生命周期的依赖项。
  2. Singleton。服务在 ServiceProvider 中解析(懒加载)时创建一次。可以依赖于任何生命周期的依赖项。不能依赖于来自分支的 ServiceProvider 实例的服务。
  3. Instance。依赖项是在 ServiceProvider 外部创建的,可以由任何其他依赖项使用。

工作原理

  1. 声明您的结构。
  2. 创建构造函数,并在其上添加 #[inject] 宏。
  3. 创建一个 ServiceProvider 对象。
  4. 使用 ServiceProvider::add_* 方法添加您的服务和依赖项。
  5. 如果需要创建本地作用域,请分支 ServiceProvider
  6. 使用 .resolve() 方法从提供者获取服务。
  7. 使用服务进行工作。

示例

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 的实例、从函数返回或作为参数传递时,这非常有用。

您需要什么

  1. ServiceProvider 初始化后粘贴以下代码:let () = service_provider;
  2. 编译器将给出一个非常大的可怕类型,从 teloc::ServiceProvider<...> 开始。
  3. 将此类型复制到类型别名中,例如 type ConcreteSP = /*编译器输出*/;
  4. 当您想要编写 ServiceProvider 实例类型时,请使用 ConcreteSP
  5. 如果您更改了 ServiceProvider 的初始化,请重复步骤 1-4。

许可证

根据您的选择,许可证为 Apache License, Version 2.0MIT 许可证
除非您明确表示,否则根据 Apache-2.0 许可证定义,您有意提交以包含在此项目中的任何贡献,将按上述方式双重许可,不附加任何其他条款或条件。

依赖关系

约 2MB
约 44K SLoC