Silentdoer

导航

Rust实现简单的IOC容器

use std::{any::{Any, TypeId}, collections::HashMap};
use once_cell::sync::Lazy;
use std::sync::Mutex;

static IOC: Lazy<Mutex<HashMap<TypeId, Box<(dyn Any + Send)>>>> = Lazy::new(|| {
    let map = HashMap::new();
    Mutex::new(map)
});

#[derive(Debug)]
struct Foo {
    cat: String,
    mouse: i32,
}

#[derive(Debug)]
struct Bar {
    pro1: String,
    pro2: i32,
    pro3: f64
}

fn main() {

    // 这里insert后应该就把锁释放了,但是为啥get不能这么写还得再学习下原理【估计是这里自动会加一个{}作用域,而get加了这个作用域导致获取的
    // 变量也在隐藏的作用域结束后释放了,所以产生了报错,提示临时变量已经被释放之类的错误
    IOC.lock().unwrap().insert(TypeId::of::<Foo>(), Box::new(Foo{cat: "aa".to_string(), mouse: 33}));
    // 上面的语句应该是会转换成这样,因此get得到的tmp_get会释放了,所以后续是无法用tmp_get的;
    /* {
        let tmp = IOC.lock.unwrap();
        tmp.insert(TypeId::of::<Foo>(), Box::new(Foo{cat: "aa".to_string(), mouse: 33}));
    } */
    IOC.lock().unwrap().insert(TypeId::of::<Bar>(), Box::new(Bar{pro1: "bb".to_string(), pro2: 66, pro3: 99.4}));

    {
        // 加了{}是为了让这个ioc_tmp在{}后释放锁,否则{}下面的removed_bar里的IOC.lock().unwrap()会一直等待锁释放来加锁【非可重入锁】
        // 所以rust其实也不是完全的线程安全,只能说常见的场景会限制;
        let ioc_tmp = IOC.lock().unwrap();

        let foo = ioc_tmp.get(&TypeId::of::<Foo>()).unwrap();
        let casted_foo = foo.downcast_ref::<Foo>();

        let bar = ioc_tmp.get(&TypeId::of::<Bar>()).unwrap();
        let casted_bar = bar.downcast_ref::<Bar>();

        println!("{:?}--{:?}", casted_foo, casted_bar);
    }

    // remove会获取value的所有权,所以函数结束后会释放掉removed_bar
    let removed_bar = IOC.lock().unwrap().remove(&TypeId::of::<Bar>()).unwrap();
    let removed_bar = removed_bar.downcast_ref::<Bar>();

    println!("{:?}", removed_bar);

    {
        let ioc_tmp = IOC.lock().unwrap();

        let none_bar = ioc_tmp.get(&TypeId::of::<Bar>());

        println!("{:?}", none_bar);
    }
}

 

posted on 2022-10-09 15:54  Silentdoer  阅读(280)  评论(0编辑  收藏  举报