use crate::ViewSet;
use async_trait::async_trait;
use reinhardt_di::{Depends, 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(),
)
})?;
let injected = Depends::<T>::resolve(&di_ctx, true).await.map_err(|e| {
reinhardt_core::exception::Error::Internal(format!(
"Dependency injection failed for {}: {:?}",
std::any::type_name::<T>(),
e
))
})?;
Ok(injected.into_inner())
}
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(),
)
})?;
let injected = Depends::<T>::resolve(&di_ctx, false).await.map_err(|e| {
reinhardt_core::exception::Error::Internal(format!(
"Dependency injection failed for {}: {:?}",
std::any::type_name::<T>(),
e
))
})?;
Ok(injected.into_inner())
}
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>>()?;
Depends::<T>::resolve(&di_ctx, true)
.await
.ok()
.map(|injected| injected.into_inner())
}
}
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<()>>();
}
}