use std::any::Any;
use std::collections::HashMap;
use std::sync::{Arc, Mutex, OnceLock, RwLock};
use ruwebframe::database;
use ruwebframe::database::TraitRedis;
enum Entry {
Factory(Box<dyn Fn() -> Box<dyn Any> + Send + Sync>),
Singleton {
factory: Box<dyn Fn() -> Box<dyn Any> + Send + Sync>,
instance: Mutex<Option<Arc<dyn Any + Send + Sync>>>,
},
}
pub struct Container {
items: HashMap<String, Entry>,
}
impl Container {
pub fn new() -> Self {
Self { items: HashMap::new() }
}
pub fn register<F, T>(&mut self, key: &str, factory: F)
where
F: Fn() -> T + Send + Sync + 'static,
T: Any + Send + Sync + 'static,
{
self.items.insert(
key.to_string(),
Entry::Factory(Box::new(move || Box::new(factory()))),
);
}
pub fn register_singleton<F, T>(&mut self, key: &str, factory: F)
where
F: Fn() -> T + Send + Sync + 'static,
T: Any + Send + Sync + 'static,
{
self.items.insert(
key.to_string(),
Entry::Singleton {
factory: Box::new(move || Box::new(factory())),
instance: Mutex::new(None),
},
);
}
pub fn get<T: Any + Clone>(&self, key: &str) -> Option<T> {
let entry = self.items.get(key)?;
match entry {
Entry::Factory(factory) => {
factory().downcast_ref::<T>().cloned()
}
_ => None,
}
}
pub fn get_singleton<T: Any + Send + Sync>(&self, key: &str) -> Option<Arc<T>> {
let entry = self.items.get(key)?;
match entry {
Entry::Singleton { factory, instance } => {
let mut guard = instance.lock().ok()?;
if guard.is_none() {
let val = *factory().downcast::<T>()
.expect("类型不匹配:注册和解析的类型不一致");
*guard = Some(Arc::new(val) as Arc<dyn Any + Send + Sync>);
}
guard.as_ref().map(|arc_any| {
arc_any.clone().downcast::<T>()
.expect("单例 Arc 类型转换失败")
})
}
_ => None,
}
}
}
static GLOBAL: OnceLock<RwLock<Container>> = OnceLock::new();
fn global() -> &'static RwLock<Container> {
GLOBAL.get_or_init(|| RwLock::new(Container::new()))
}
pub fn register<F, T>(key: &str, factory: F)
where
F: Fn() -> T + Send + Sync + 'static,
T: Any + Send + Sync + 'static,
{
global().write().unwrap().register(key, factory);
}
pub fn register_singleton<F, T>(key: &str, factory: F)
where
F: Fn() -> T + Send + Sync + 'static,
T: Any + Send + Sync + 'static,
{
global().write().unwrap().register_singleton(key, factory);
}
pub fn get<T: Any + Clone>(key: &str) -> Option<T> {
global().read().unwrap().get(key)
}
pub fn get_singleton<T: Any + Send + Sync>(key: &str) -> Option<Arc<T>> {
global().read().unwrap().get_singleton(key)
}
#[derive(Debug)]
struct Database {
id: u64,
}
impl Database {
fn new() -> Self {
println!(">>> Database::new() 执行");
Self { id: rand::random() }
}
}
#[derive(Debug,Clone)]
struct Logger;
impl Logger {
fn new() -> Self {
println!(">>> Logger::new() 执行");
Self
}
}
#[test]
fn test01_container() {
register_singleton("db", Database::new);
register("logger", Logger::new);
let db1 = get_singleton::<Database>("db").unwrap();
let db2 = get_singleton::<Database>("db").unwrap();
println!("Arc::ptr_eq(db1, db2) = {}", Arc::ptr_eq(&db1, &db2));
let log1 = get::<Logger>("logger").unwrap();
let log2 = get::<Logger>("logger").unwrap();
println!("多例: log1={:?}, log2={:?} ", log1, log2 );
}
pub fn get_db() -> Option<Arc<Database>> {
get_singleton::<Database>("db")
}
#[test]
fn test_02_log() {
let cli=database::find_bean_redis_client()
.unwrap();
let v= cli.set_key("my_key", "1111");
println!("{:?}", v.unwrap());
let v = cli.get_key("my_key");
println!("{:?}", v.unwrap());
let v = cli.del_key("my_key");
}