我不认为直接这样做是可能的,但是如果你的类型 T 可以序列化,那么这里有一个方法。让listeners 成为Vec<Arc<dyn Fn(String)>>,并在插入此 Vec 时,传递一个从 String 转换为 T 的 lambda 并调用实际的侦听器函数。这是我的意思的工作代码:
use std::sync::Arc;
struct EventEmitter {
listeners: Vec<Arc<dyn Fn(String)>>,
}
impl EventEmitter {
pub fn add_listener<T>(&mut self, listener: Arc<dyn Fn(T)>)
where
T: std::str::FromStr, // So that `s` can be converted to type `t`.
<T as std::str::FromStr>::Err: std::fmt::Debug, // So that `e` can be printed.
T: 'static, // See https://stackoverflow.com/a/29740792/8111265
{
self.listeners.push(Arc::new(move |s| {
match s.parse::<T>() {
Ok(t) => listener(t),
Err(e) => println!("Oops! we couldn't convert {:?} to type T due to {:?}", s, e),
};
}));
}
pub fn notify(&self, s: &str) {
for listener in self.listeners.iter() {
listener(s.to_string());
}
}
}
#[test]
fn test_event_emitter() {
let mut e = EventEmitter { listeners: vec![] };
// i32 implements `std::str::FromStr`.
e.add_listener(Arc::new(|x: i32| {
println!("Got {:?} in i32 listener", x);
}));
// std::net::IpAddr implements `std::str::FromStr`.
e.add_listener(Arc::new(|ip_addr: std::net::IpAddr| {
println!("Got {:?} in IpAddr listener", ip_addr);
}));
// This line prints:
// Got 42 in i32 listener
// Oops! we couldn't convert "42" to type T due to AddrParseError(())
e.notify("42");
// This line prints:
// Oops! we couldn't convert "127.0.0.1" to type T due to ParseIntError { kind: InvalidDigit }
// Got V4(127.0.0.1) in IpAddr listener
e.notify("127.0.0.1");
}
这个想法可以再细化一点:也许不需要一些 Arcs,也许有比 String 更好的“基本”类型(可能这可以用于任何与 serde 一起使用的类型),您可以使用 &str 代替 String 原样。
既然您询问了有关使用 serde 的问题,这里有一个示例:
use serde::{Deserialize, Serialize};
use std::sync::Arc;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct PointInts {
x: i32,
y: i32,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct PointFloats {
x: f32,
y: f32,
}
struct EventEmitter {
listeners: Vec<Arc<dyn Fn(&[u8])>>,
}
impl EventEmitter {
pub fn add_listener<T>(&mut self, listener: Arc<dyn Fn(T)>)
where
T: serde::de::DeserializeOwned,
T: 'static, // See https://stackoverflow.com/a/29740792/8111265
{
self.listeners.push(Arc::new(move |bytes| {
match bincode::deserialize(bytes) {
Ok(t) => listener(t),
Err(e) => println!(
"Oops! we couldn't convert the bytes {:?} to type T due to {:?}",
bytes, e
),
};
}));
}
pub fn notify<T>(&self, obj: T)
where
T: serde::Serialize,
{
let bytes = bincode::serialize(&obj).unwrap();
for listener in self.listeners.iter() {
listener(&bytes);
}
}
}
#[test]
fn test_event_emitter() {
let mut e = EventEmitter { listeners: vec![] };
// PoinitInts implements Serialize and Deserialize.
e.add_listener(Arc::new(|p: PointInts| {
println!("Got {:?} in PointInts listener", p);
}));
// PointFloats implements Serialize and Deserialize.
e.add_listener(Arc::new(|p: PointFloats| {
println!("Got {:?} in PointFloats listener", p);
}));
// This line prints:
// Got PointInts { x: 42, y: 999 } in PointInts listener
// Got PointFloats { x: 0.000000000000000000000000000000000000000000059, y: 0.0000000000000000000000000000000000000000014 } in PointFloats listener
e.notify(PointInts { x: 42, y: 999 });
// This line prints:
// Got PointInts { x: 1109917696, y: 1120327434 } in PointInts listener
// Got PointFloats { x: 42.0, y: 99.42 } in PointFloats listener
e.notify(PointFloats { x: 42.0, y: 99.420 });
}
请注意,如果字节可以转换为给定的请求结构,bincode::deserialize 将返回Ok(_),因此您会在上面看到奇怪的值(可能有一种方法可以添加类型标记以便“错误”结构不要反序列化)。