I'm trying to implement the Abstract Factory pattern
pub trait EventStore: Debug {
fn create_stream<T: Codable>(&self, name: String) -> Result<Box<dyn EventStream<T>>, EventStoreError>;
}
The event stream receives events, serializes them and deserializes them using their type information:
#[async_trait(?Send)]
pub trait EventStream<T>: Debug + 'static {
async fn append(&mut self, events: &[T]) -> Result<(), EventStreamError>;
async fn events<'a>(&'a mut self) -> Result<&'a [T], EventStreamError>
where
T: 'a;
}
A current sample usage is:
pub struct Test<T: Codable> {
stream: Box<dyn EventStream<T>>,
}
impl<T: Codable> Test<T> {
pub fn new<E: EventStore>(event_store: E) -> Self {
Self { stream: event_store.create_stream::<T>("test".to_string()).unwrap() }
}
pub async fn has_events(&mut self) -> bool {
if let Ok(events) = self.stream.events().await {
events.len() > 0
} else {
false
}
}
}
And it works pretty well, as long as I use it that way, the problem is if I try to use it as an Rc:
pub fn new(event_store: Rc<dyn EventStore>) -> Self {
Self { stream: event_store.create_stream::<T>("test".to_string()).unwrap() }
}
error[E0038]: the trait `EventStore` cannot be made into an object
I think I understood well enough why this approach isn't supported, but I still believe there should be a smarter way to implement this in rust.
The implementations of the Trait are dependency inject as they are supposed to be, so those enum dispatch strategies variants, I can't use.
I have tried several approaches using impl dyn, but I ended always loosing the type that I need in the concrete implementation to create the proper EventStream.
I appreciate all the help I can get, because for sure I'm missing something.
Thank you!