前段时间一直在思考虽然之前发布的配置文件读取库可以使用,但总感觉可拓展性太差了,万一哪天我需要读取json配置呢!所以绞尽脑汁想到了一个不算完美的解决方案,该方案是实现n版后的简洁版,直接上代码:
先定义通用文件读取以及文件访问接口
// 文件读取统一接口
pub trait ConfReadImpl {
// path: 文件路径
fn read_conf(&mut self, path: &str) -> Result<i32, Error>;
}
// 获取读取后的值
pub trait GetConfImpl {
fn get_string(&self, key: &str) -> String;
fn def_get_i32(&self, key: &str, def: i32) -> i32;
fn def_get_u32(&self, key: &str, def: u32) -> u32;
fn def_get_f32(&self, key: &str, def: f32) -> f32;
fn def_get_f64(&self, key: &str, def: f64) -> f64;
fn def_get_bool(&self, key: &str, def: bool) -> bool;
fn get_i32(&self, key: &str) -> i32;
fn get_u32(&self, key: &str) -> u32;
fn get_f32(&self, key: &str) -> f32;
fn get_f64(&self, key: &str) -> f64;
fn get_bool(&self, key: &str) -> bool;
}
定义统一调用文件方式
// 定义统一对外访问接口
pub trait ConfImpl: GetConfImpl + ConfReadImpl{}
// 给实现了GetConfImpl 和ConfReadImpl 的类型默认实现ConfImpl
impl <T> ConfImpl for T where T: GetConfImpl + ConfReadImpl {}
pub struct Conf {
conf_map: HashMap<String, Box<dyn ConfImpl>>,
}
impl Conf {
pub fn new () -> Self {
Self {
conf_map: HashMap::new(),
}
}
}
impl Conf {
// 初始化配置
pub fn init(&mut self, key: &str, path: &str) -> &Box<dyn ConfImpl> {
self.read_conf(key, path);
return self.conf_map.get(key).unwrap();
}
// 初始化配置 - 读取配置文件
fn read_conf(&mut self, key: &str, path: &str) {
// 防止多次调用
if self.conf_map.is_empty() {
self.register_conf();
} else {
return;
}
if !self.conf_map.contains_key(key) {
panic!("不存在指定的功能模块");
}
let conf = self.conf_map.get_mut(key).unwrap();
// 读取文件
let new_conf = conf.as_mut();
if let Err(e) = new_conf.read_conf(path) {
panic!(e);
}
}
// 注册配置文件读取器 - 这一步是手动的
fn register_conf(&mut self) {
self.conf_map.insert("ini".to_string(), Box::new(ConfIni::new()));
}
}
main.rs 调用
fn main() {
let mut conf = Conf::new();
let new_conf = conf.init("ini", "web/app.conf");
println!("{}", new_conf.get_string("server::test"));
println!("{}", new_conf.get_string("my_str"));
}
到此全部完成,更多详情可下载源码查看 源码下载