Unable to register and resolve a singleton from the service container using Arc<dyn ...>
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 条评论