ITADN

Unable to register and resolve a singleton from the service container using Arc<dyn ...>

#38Openelertan 创建于 2023-09-22
E
elertancommented
I'm trying to register and resolve a singleton from the service container using `Arc<dyn ...>`, but cannot figure out as to why this does not work. At first I tried to register the service using `add_singleton_c` by registering it as an `Arc<MyServiceImpl>` directly but that the conversion to `Arc<dyn MyService>` impossible to implement using `From<_>` due to the orphan rule. Even though this works on `Box<_>` just fine. Then I tried to introduce a `Wrapper` type which wraps the `Arc` like so `Wrapper(Arc<MyServiceImpl>)`. I thought this was necessary to implement the conversion, but currently that results in getting the error: `the trait ResolveContainer<'_, Wrapper, _> is not implemented for SingletonContainer<Wrapper>`. Even though I think I implemented all the necessary traits on the types for it to implement `ResolveContainer`. I have created a small POC which should showcase the issue: ```rs use std::sync::Arc; use async_trait::async_trait; use teloc::{Dependency, DependencyClone, Resolver, ServiceProvider}; #[async_trait] pub trait MyService { async fn ping(&self); } #[async_trait] impl MyService for MyServiceImpl { async fn ping(&self) { println!("Pong!"); } } pub struct MyServiceImpl {} #[teloc::inject] impl MyServiceImpl { fn di_init() -> Self { Self {} } } // Unable to implement due to orphan rule... // impl From<Arc<ExchangeImpl>> for Arc<dyn Exchange> { // fn from(value: Arc<ExchangeImpl>) -> Self { // value.clone() // } // } // or even... // impl From<&Arc<ExchangeImpl>> for Arc<dyn Exchange> { // fn from(value: &Arc<ExchangeImpl>) -> Self { // value.clone() // } // } pub struct Wrapper(Arc<MyServiceImpl>); #[teloc::inject] impl Wrapper { fn di_init() -> Self { Self(Arc::new(MyServiceImpl {})) } } impl Clone for Wrapper { fn clone(&self) -> Self { Self(self.0.clone()) } } impl DependencyClone for Wrapper {} impl From<Wrapper> for Arc<dyn MyService> { fn from(value: Wrapper) -> Self { value.0.clone() } } impl From<Box<MyServiceImpl>> for Box<dyn MyService> { fn from(value: Box<MyServiceImpl>) -> Self { value } } #[tokio::main] async fn main() -> anyhow::Result<()> { // This won't work since you cannot implement `From<Arc<ExchangeImpl>>` for `Arc<dyn Exchange>` // as it is not defined in this crate or marked as #[fundamental] like `Box<_>` is. // let sp = ServiceProvider::new().add_singleton_c::<Arc<dyn Exchange>, Arc<ExchangeImpl>>(); let sp = ServiceProvider::new().add_singleton_c::<Arc<dyn MyService>, Wrapper>(); let service: Arc<dyn MyService> = sp.resolve(); // However using a box like this, works fine. // let sp = ServiceProvider::new().add_transient_c::<Box<dyn MyService>, Box<MyServiceImpl>>(); // let exchange: Box<dyn MyService> = sp.resolve(); service.ping().await; Ok(()) } ```
2 条评论