use crate::ViewSet;
use async_trait::async_trait;
use reinhardt_di::{Injectable, InjectionContext};
use reinhardt_http::{Request, Result};
use std::sync::Arc;
#[async_trait]
pub trait InjectableViewSet: ViewSet {
async fn resolve<T>(&self, request: &Request) -> Result<T>
where
T: Injectable + Clone + Send + Sync + 'static,
{
let di_ctx = request
.get_di_context::<Arc<InjectionContext>>()
.ok_or_else(|| {
reinhardt_core::exception::Error::Internal(
"DI context not set. Ensure the router is configured with .with_di_context()"
.to_string(),
)
})?;
match di_ctx.resolve::<T>().await {
Ok(injected) => Ok(injected.as_ref().clone()),
Err(reinhardt_di::DiError::DependencyNotRegistered { .. }) => {
T::inject(&di_ctx).await.map_err(|e| {
reinhardt_core::exception::Error::Internal(format!(
"Dependency injection failed for {}: {:?}",
std::any::type_name::<T>(),
e
))
})
}
Err(e) => Err(reinhardt_core::exception::Error::Internal(format!(
"Dependency injection failed for {}: {:?}",
std::any::type_name::<T>(),
e
))),
}
}
async fn resolve_uncached<T>(&self, request: &Request) -> Result<T>
where
T: Injectable + Clone + Send + Sync + 'static,
{
let di_ctx = request
.get_di_context::<Arc<InjectionContext>>()
.ok_or_else(|| {
reinhardt_core::exception::Error::Internal(
"DI context not set. Ensure the router is configured with .with_di_context()"
.to_string(),
)
})?;
T::inject_uncached(&di_ctx).await.map_err(|e| {
reinhardt_core::exception::Error::Internal(format!(
"Dependency injection failed for {}: {:?}",
std::any::type_name::<T>(),
e
))
})
}
async fn try_resolve<T>(&self, request: &Request) -> Option<T>
where
T: Injectable + Clone + Send + Sync + 'static,
{
let di_ctx = request.get_di_context::<Arc<InjectionContext>>()?;
match di_ctx.resolve::<T>().await {
Ok(injected) => Some(injected.as_ref().clone()),
Err(reinhardt_di::DiError::DependencyNotRegistered { .. }) => {
T::inject(&di_ctx).await.ok()
}
Err(_) => None,
}
}
}
impl<V: ViewSet> InjectableViewSet for V {}
#[cfg(test)]
mod tests {
use super::*;
use crate::viewsets::GenericViewSet;
#[test]
fn test_injectable_viewset_trait_is_implemented() {
fn assert_injectable<T: InjectableViewSet>() {}
assert_injectable::<GenericViewSet<()>>();
}
}