4 个版本

0.1.3 2022年6月14日
0.1.2 2022年6月9日
0.1.1 2022年6月9日
0.1.0 2022年6月9日

#321 in 测试

每月下载量 44

GPL-3.0-only

19KB
110 代码行

dose

Current Crates.io Version

每日一剂的结构和函数。

特性

  • 简洁 👌
  • 飞速快速 🏎️💨
  • 懒加载实例 🦥
  • 静态检查 🕵️‍♀️
  • 依赖注入 💉
  • 声明式接口 ✨
  • 无运行时依赖图 🎉

遗憾的是,我们目前不支持运行时依赖循环检测...

使用方法

初始化

您需要在项目根目录的 init! 宏中初始化该 crate。这是 Rust 的当前限制,这可能在未来的版本中变得不再必要。

dose::init!();

注册提供者

您可以使用 provide 属性注册提供者。

#[provide]
fn provide_something(context: &mut Context<Config>) -> Something {
    Something::new(...)
}

&mut Context<Config> 总是作为参数传递,并可用于解析其他类型。配置也存在于上下文 context.config 中。

每次类型 Something 被调用 get! 时,都会调用上述函数。如果希望使用相同的实例,则需要将属性参数 singleton 设置为 true

#[provide(singleton=true)]
fn provide_something(context: &mut Context<Config>) -> Something {
    Something::new(...)
}

在这种情况下,每次类型 Something 被调用 get! 时,都会进行实例克隆。如果类型 Something 被封装在 std::sync::Arcstd::rc::Rc 中,它实际上成为一个单例。

#[provide(singleton=true)]
fn provide_something(context: &mut Context<Config>) -> Arc<Something> {
    Arc::new(Something::new(...))
}

解析实例

get! 宏是获取类型实例的方法。

let mut context = dose::Context::new(config);
let my_type: MyType = dose::get!(context);

此宏也可以在提供者内部使用。

struct MyType {
    a: TypeA,
    b: TypeB,
}

#[provide]
fn provide_my_type(context: &mut Context<Config>) -> MyType {
    MyType {
        a: get!(context), // Type infered to TypeA
        b: get!(context), // Type infered to TypeB
    }
}

请注意,如果 TypeATypeB 的提供者未注册,则会出现编译错误。

良好实践

模块分离

提供者应定义在专门创建的模块中,用于声明每种类型的实例化方式。

上下文生命周期

在应用程序启动之前,应删除(dropContext<Config>

使用范围外。

use dose::{Context, get}

... // declare all modules

fn create_server(config: Config) -> Server {
    let mut context = Context::new(config);
    get!(context) 
}

#[tokio::main]
async fn start_server_implicit() {
    let server = create_server(Config::load(...));
    // Implicitly drop the context because it becomes out of scope
    server.start().await
}

#[tokio::main]
async fn start_server_explicit() {
    let mut context = Context::new(config);
    let server: Server = get!(context);
    // Explicitly drop the context using std::mem::drop
    std::mem::drop(context);
    server.start().await
}

提供者单一用途

保持提供者简单,其中只应包含创建逻辑。不应执行算法或领域逻辑。

配置

上下文中提供的配置可以是任何内容,但可以使用没有函数和公共字段的简单结构体。每个提供者只需上下文和配置即可正确执行。

依赖关系

~1.5MB
~37K SLoC