我试图建立一个可用的工厂列表,以建立不同种类的处理器在 rust 。
pub trait MyHandler {
fn handle();
}
pub trait MyFactory {
fn build() -> Result<Box<dyn MyHandler>, dyn Error>;
}
我有一些具体的处理程序(Foo,和类似的酒吧和巴兹...):
pub struct MyFoo;
impl MyHandler for MyFoo {
fn handle() {
println!("Foo handler");
}
}
impl MyFactory for MyFoo {
fn build() -> Result<Box<dyn MyHandler>, dyn Error> {
// Do something that may fail
Ok(MyFoo {})
}
}
现在,我想构建一个“按名称列出的可用处理程序的全局表”。
到目前为止,我试过:
const NOTIFIERS: HashMap<(&str, dyn Fn() -> Result<Box<dyn MyHandler>, Box<dyn Error>)>;
不起作用,因为我必须.insert()
数据,但常量不能修改。- 不编译的
const NOTIFIERS: Vec<(&str, Box<dyn Fn() -> Result<Box<dyn MyHandler>, Box<dyn Error>>>)> = vec![ ("foo", Box::new(MyFoo::build)), ("bar", Box::new(MyBar::build)), ("baz", Box::new(MyBaz::build))];
,因为常量中不允许分配
我的目标是这种结构,这样我就可以:
- 在添加/删除处理程序时,具有要更新的单一事实源
- 我有一个名称列表,可以轻松地在API或CLI中迭代和提供
- 我有一个简单的全局处理程序工厂,可以在其中查找处理程序名称并调用构建
除了上述两种尝试之外,
- 我想使用一个枚举,其中每个类型都是
(&str, closure)
的元组,我可以使用strum
板条箱对其进行迭代,但它会在枚举变体(类型)上进行迭代,我仍然必须从其他地方设置枚举值(名称和闭包)... - 我想我可能会使用宏来自动填充处理程序列表,方法是“简单地”向每种类型的处理程序添加一个
#[derive(RegisterHandler)
,但我对Rust太陌生了,不了解关于宏的任何东西,即使它是在构建时生成的,我仍然会有同样的“问题”,即如何将结果结构“存储”为特定类型的常量。
现在,我手动硬编码处理程序名称两次:一次是提供处理程序类型列表,第二次是匹配请求的处理程序名以调用其工厂。它可以工作,但看起来不优雅。
我可以按名称构建“全球工厂”吗?如何“正确”地构建?
1条答案
按热度按时间ruarlubt1#
这绝对有可能,你只需要做一些调整。
使用静态,而不是常量。
一个
const
变量在使用站点被“复制”。这通常不是你想要的。相反,你可以使用一个static
变量--它在程序中只有一个示例。一个static
变量仍然需要一个const初始化器。保持简单。
你不需要
MyFactory
trait,Rust很好地理解了函数指针:Error
。*把这些放在一起。
完整的with playground link示例:
FACTORIES
。相反,我会将其私有化,并公开一个函数来执行查找,并在失败时提供一个漂亮的错误消息。*