use service::*;
use factory::*;
use invocation_method::*;
use downcast::Downcast;
use std::any::Any;
use std::borrow::Borrow;
use std::collections::BTreeMap;
use std::fmt::Debug;
use std::sync::RwLock;
pub struct Ioc<Key = str, Base: ?Sized = DefaultBase> {
services: BTreeMap<Key, RwLock<Box<Base>>>,
}
impl<Key, Base: ?Sized> Ioc<Key, Base>
where Key: Debug + Ord, Base: Any
{
#[doc(hidden)]
pub fn new(services: BTreeMap<Key, RwLock<Box<Base>>>) -> Self {
Ioc{ services: services }
}
pub fn services(&self) -> &BTreeMap<Key, RwLock<Box<Base>>> { &self.services }
pub fn invoke<'a, M>(&'a self, args: M::Args) -> Result<M::Ret, M::Error>
where M: InvocationMethod<'a, Key, Base>,
{
M::invoke(&self.services, args)
}
pub fn read<'a, Svc>(
&'a self
) -> Result<ServiceReadGuard<Svc, Base>, LockError<&'static Svc::Key>>
where Svc: ServiceReflect, Key: Borrow<Svc::Key>, Base: Downcast<Svc>
{
self.invoke::<Read<Svc>>(())
}
pub fn write<'a, Svc>(
&'a self
) -> Result<ServiceWriteGuard<Svc, Base>, LockError<&'static Svc::Key>>
where Svc: ServiceReflect, Key: Borrow<Svc::Key>, Base: Downcast<Svc>
{
self.invoke::<Write<Svc>>(())
}
pub fn create<'a, Obj>(
&'a self,
args: <Obj::Factory as Factory<Obj>>::Args,
) -> Result<Obj, CreationError<&'static <Obj::Factory as ServiceReflect>::Key, <Obj::Factory as Factory<Obj>>::Error>>
where
Obj: FactoryObject,
Obj::Factory: ServiceReflect,
Key: Borrow<<Obj::Factory as ServiceReflect>::Key>,
Base: Downcast<Obj::Factory>,
{
self.invoke::<Create<Obj>>(args)
}
pub fn read_all(&self) -> Result<ServiceReadGuardMap<Key, Base>, LockError<&Key>> {
self.invoke::<ReadAll>(())
}
pub fn write_all(&self) -> Result<ServiceWriteGuardMap<Key, Base>, LockError<&Key>> {
self.invoke::<WriteAll>(())
}
}
pub struct IocBuilder<Key = str, Base: ?Sized = DefaultBase> {
services: BTreeMap<Key, RwLock<Box<Base>>>,
}
impl<Key, Base: ?Sized> IocBuilder<Key, Base>
where Key: Debug + Ord, Base: Any
{
pub fn new() -> Self {
IocBuilder{ services: BTreeMap::new() }
}
pub fn register_service(&mut self, key: Key, svc: Box<Base>) -> &mut Self {
self.services.insert(key, RwLock::new(svc));
self
}
pub fn register<Svc>(&mut self, svc: Svc) -> &mut Self
where Svc: ServiceReflect,
Svc::Key: ToOwned<Owned = Key>,
Key: Borrow<Svc::Key>, Box<Svc>: Into<Box<Base>>,
{
let key = Svc::key();
self.register_service(key.to_owned(), Box::new(svc).into())
}
pub fn build(self) -> Ioc<Key, Base> {
Ioc::new(self.services)
}
}