< 返回版块

ZihanType 发表于 2023-08-29 15:27

Tags:依赖注入, dependency-injection, DI, IOC

Rudi

Rudi,一个开箱即用的依赖注入框架。

在 0.4.0 版本中,我新增了条件注册的功能,就像 Spring 中的 @Conditional 注解一样,你可以通过定义一个fn(&Context) -> bool的函数来判断是否注册某个实例。这个功能最大的用处就是根据环境变量或者配置文件,决定注册哪些实例,尤其是在测试的时候,可以根据不同的测试环境,注册不同的实例。

示例

use std::{collections::HashMap, env, fmt::Debug, rc::Rc};

use rudi::{Context, Singleton, Transient};

#[derive(Clone)]
struct Environment {
    map: HashMap<String, String>,
}

// 表示环境变量的实例,会在 Context 初始化的时候就创建
#[Singleton(eager_create)]
impl Environment {
    fn new() -> Self {
        Self {
            map: env::vars().collect(),
        }
    }
}

trait Service: Debug {}

fn transfer<T: Service + 'static>(t: T) -> Rc<dyn Service> {
    Rc::new(t)
}

// 判断环境变量中,key 为 env 的值是否等于 value
fn condition(cx: &Context, value: &str) -> bool {
    cx.get_singleton::<Environment>()
        .map
        .get("env")
        .map(|a| a == value)
        .unwrap_or(false)
}

// 如果环境变量中的 env 为 dev,则注册 A
#[derive(Debug)]
#[Transient(condition = |cx| condition(cx, "dev"), binds = [transfer])]
struct A;

impl Service for A {}

// 如果环境变量中的 env 为 prod,则注册 B
#[derive(Debug)]
#[Transient(condition = |cx| condition(cx, "prod"), binds = [transfer])]
struct B;

impl Service for B {}

fn main() {
    // 设置环境变量 env 为 dev
    env::set_var("env", "dev");
    let mut cx = Context::auto_register();
    let svc = cx.resolve::<Rc<dyn Service>>();
    // 由于 A 的条件注册为 dev,所以会注册 A
    assert_eq!(format!("{:?}", svc), "A");

    // 设置环境变量 env 为 prod
    env::set_var("env", "prod");
    let mut cx = Context::auto_register();
    let svc = cx.resolve::<Rc<dyn Service>>();
    // 由于 B 的条件注册为 prod,所以会注册 B
    assert_eq!(format!("{:?}", svc), "B");
}

更多的信息可以在仓库上看到。

Rudi

欢迎各位使用,有问题欢迎提 issue,如果觉得好用,可以点个 star。

评论区

写评论

还没有评论

1 共 0 条评论, 1 页