use std::any::TypeId;
pub trait Injectable: Send + Sync + 'static {
#[inline]
fn type_id_of() -> TypeId
where
Self: Sized,
{
TypeId::of::<Self>()
}
#[inline]
fn type_name_of() -> &'static str
where
Self: Sized,
{
std::any::type_name::<Self>()
}
}
impl<T: Send + Sync + 'static> Injectable for T {}
pub trait Provider: Injectable {}
impl<T: Injectable> Provider for T {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Lifetime {
#[default]
Singleton,
Lazy,
Transient,
Scoped,
}
#[derive(Clone)]
pub struct ProviderRegistration {
pub type_id: TypeId,
pub type_name: &'static str,
pub register_fn: fn(&crate::Container),
}
impl ProviderRegistration {
#[inline]
pub fn new<T: Injectable>(register_fn: fn(&crate::Container)) -> Self {
Self {
type_id: TypeId::of::<T>(),
type_name: std::any::type_name::<T>(),
register_fn,
}
}
pub fn singleton<T: Injectable + Clone>(_value: T) -> Self {
Self {
type_id: TypeId::of::<T>(),
type_name: std::any::type_name::<T>(),
register_fn: |_container| {
},
}
}
}
impl std::fmt::Debug for ProviderRegistration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ProviderRegistration")
.field("type_id", &self.type_id)
.field("type_name", &self.type_name)
.finish()
}
}
#[macro_export]
macro_rules! provider {
($type:ty, $factory:expr) => {
$crate::ProviderRegistration {
type_id: std::any::TypeId::of::<$type>(),
type_name: std::any::type_name::<$type>(),
register_fn: |container| {
container.singleton($factory);
},
}
};
(lazy $type:ty, $factory:expr) => {
$crate::ProviderRegistration {
type_id: std::any::TypeId::of::<$type>(),
type_name: std::any::type_name::<$type>(),
register_fn: |container| {
container.lazy($factory);
},
}
};
(transient $type:ty, $factory:expr) => {
$crate::ProviderRegistration {
type_id: std::any::TypeId::of::<$type>(),
type_name: std::any::type_name::<$type>(),
register_fn: |container| {
container.transient($factory);
},
}
};
}