diff options
| author | HampusM <hampus@hampusmat.com> | 2023-08-20 17:01:12 +0200 | 
|---|---|---|
| committer | HampusM <hampus@hampusmat.com> | 2023-08-20 17:01:12 +0200 | 
| commit | 0b4232d343e2214ead8fa62583bff2e948173ddf (patch) | |
| tree | f809051c9933a132971ab91244e83d1f9d387ad6 /src/di_container | |
| parent | be2c39b452b8b1e024300caff1ce8f11d54b27ce (diff) | |
feat: expose DI container get_bound methods to public API
Diffstat (limited to 'src/di_container')
| -rw-r--r-- | src/di_container/asynchronous/mod.rs | 85 | ||||
| -rw-r--r-- | src/di_container/binding_storage.rs | 11 | ||||
| -rw-r--r-- | src/di_container/blocking/mod.rs | 66 | ||||
| -rw-r--r-- | src/di_container/mod.rs | 33 | 
4 files changed, 162 insertions, 33 deletions
diff --git a/src/di_container/asynchronous/mod.rs b/src/di_container/asynchronous/mod.rs index 2939ddd..e5f7f5d 100644 --- a/src/di_container/asynchronous/mod.rs +++ b/src/di_container/asynchronous/mod.rs @@ -59,6 +59,7 @@ use async_trait::async_trait;  use crate::di_container::asynchronous::binding::builder::AsyncBindingBuilder;  use crate::di_container::binding_storage::DIContainerBindingStorage; +use crate::di_container::BindingOptions;  use crate::errors::async_di_container::AsyncDIContainerError;  use crate::future::BoxFuture;  use crate::private::cast::arc::CastArc; @@ -116,14 +117,50 @@ pub trait IAsyncDIContainer:          'a: 'b,          Self: 'b; -    #[doc(hidden)] -    async fn get_bound<Interface>( -        self: &Arc<Self>, +    /// Returns the type bound with `Interface` where the binding has the specified +    /// options. +    /// +    /// `dependency_history` is passed to the bound type when it is being resolved. +    /// +    /// # Errors +    /// Will return `Err` if: +    /// - No binding for `Interface` exists +    /// - Resolving the binding for `Interface` fails +    /// - Casting the binding for `Interface` fails +    /// +    /// # Examples +    /// ``` +    /// # use syrette::di_container::asynchronous::AsyncDIContainer; +    /// # use syrette::di_container::asynchronous::IAsyncDIContainer; +    /// # use syrette::dependency_history::DependencyHistory; +    /// # use syrette::di_container::BindingOptions; +    /// # +    /// # struct EventHandler {} +    /// # struct Button {} +    /// # +    /// # Box::pin(async { +    /// # let di_container = AsyncDIContainer::new(); +    /// # +    /// let mut dependency_history = DependencyHistory::new(); +    /// +    /// dependency_history.push::<EventHandler>(); +    /// +    /// di_container +    ///     .get_bound::<Button>(dependency_history, BindingOptions::new().name("huge")) +    ///     .await?; +    /// # +    /// # Ok::<_, Box<dyn std::error::Error>>(()) +    /// # }); +    /// ``` +    fn get_bound<'this, 'fut, Interface>( +        self: &'this Arc<Self>,          dependency_history: DependencyHistory, -        name: Option<&'static str>, -    ) -> Result<SomePtr<Interface>, AsyncDIContainerError> +        binding_options: BindingOptions<'static>, +    ) -> BoxFuture<'fut, Result<SomePtr<Interface>, AsyncDIContainerError>>      where -        Interface: 'static + ?Sized + Send + Sync; +        Interface: 'static + 'this + ?Sized + Send + Sync, +        'this: 'fut, +        Self: 'fut;  }  /// Async dependency injection container. @@ -163,7 +200,7 @@ impl IAsyncDIContainer for AsyncDIContainer          Self: 'b,      {          Box::pin(async { -            self.get_bound::<Interface>(DependencyHistory::new(), None) +            self.get_bound::<Interface>(DependencyHistory::new(), BindingOptions::new())                  .await          })      } @@ -178,24 +215,34 @@ impl IAsyncDIContainer for AsyncDIContainer          Self: 'b,      {          Box::pin(async { -            self.get_bound::<Interface>(DependencyHistory::new(), Some(name)) -                .await +            self.get_bound::<Interface>( +                DependencyHistory::new(), +                BindingOptions::new().name(name), +            ) +            .await          })      } -    async fn get_bound<Interface>( -        self: &Arc<Self>, +    fn get_bound<'this, 'fut, Interface>( +        self: &'this Arc<Self>,          dependency_history: DependencyHistory, -        name: Option<&'static str>, -    ) -> Result<SomePtr<Interface>, AsyncDIContainerError> +        binding_options: BindingOptions<'static>, +    ) -> BoxFuture<'fut, Result<SomePtr<Interface>, AsyncDIContainerError>>      where -        Interface: 'static + ?Sized + Send + Sync, +        Interface: 'static + 'this + ?Sized + Send + Sync, +        'this: 'fut, +        Self: 'fut,      { -        let binding_providable = self -            .get_binding_providable::<Interface>(name, dependency_history) -            .await?; - -        self.handle_binding_providable(binding_providable).await +        Box::pin(async move { +            let binding_providable = self +                .get_binding_providable::<Interface>( +                    binding_options.name, +                    dependency_history, +                ) +                .await?; + +            self.handle_binding_providable(binding_providable).await +        })      }  } diff --git a/src/di_container/binding_storage.rs b/src/di_container/binding_storage.rs index 2bc208f..3c3c565 100644 --- a/src/di_container/binding_storage.rs +++ b/src/di_container/binding_storage.rs @@ -6,7 +6,7 @@ pub struct DIContainerBindingStorage<Provider>  where      Provider: 'static + ?Sized,  { -    inner: AHashMap<BindingIdentification, Box<Provider>>, +    inner: AHashMap<BindingIdentification<'static>, Box<Provider>>,  }  impl<Provider> DIContainerBindingStorage<Provider> @@ -21,7 +21,10 @@ where      }      #[allow(clippy::borrowed_box)] -    pub fn get<Interface>(&self, name: Option<&'static str>) -> Option<&Box<Provider>> +    pub fn get<'me, Interface>( +        &'me self, +        name: Option<&'me str>, +    ) -> Option<&'me Box<Provider>>      where          Interface: 'static + ?Sized,      { @@ -77,10 +80,10 @@ where  }  #[derive(Debug, PartialEq, Eq, Hash)] -struct BindingIdentification +struct BindingIdentification<'a>  {      type_id: TypeId, -    name: Option<&'static str>, +    name: Option<&'a str>,  }  #[cfg(test)] diff --git a/src/di_container/blocking/mod.rs b/src/di_container/blocking/mod.rs index 5a27f78..5b0acc8 100644 --- a/src/di_container/blocking/mod.rs +++ b/src/di_container/blocking/mod.rs @@ -56,6 +56,7 @@ use std::rc::Rc;  use crate::di_container::binding_storage::DIContainerBindingStorage;  use crate::di_container::blocking::binding::builder::BindingBuilder; +use crate::di_container::BindingOptions;  use crate::errors::di_container::DIContainerError;  use crate::private::cast::boxed::CastBox;  use crate::private::cast::rc::CastRc; @@ -103,16 +104,57 @@ pub trait IDIContainer: Sized + 'static + details::DIContainerInternals      where          Interface: 'static + ?Sized; -    #[doc(hidden)] +    /// Returns the type bound with `Interface` where the binding has the specified +    /// options. +    /// +    /// `dependency_history` is passed to the bound type when it is being resolved. +    /// +    /// # Errors +    /// Will return `Err` if: +    /// - No binding for `Interface` exists +    /// - Resolving the binding for `Interface` fails +    /// - Casting the binding for `Interface` fails +    /// +    /// # Examples +    /// ```no_run +    /// # use syrette::di_container::blocking::DIContainer; +    /// # use syrette::di_container::blocking::IDIContainer; +    /// # use syrette::dependency_history::DependencyHistory; +    /// # use syrette::di_container::BindingOptions; +    /// # +    /// # struct EventHandler {} +    /// # struct Button {} +    /// # +    /// # fn main() -> Result<(), Box<dyn std::error::Error>> { +    /// # let di_container = DIContainer::new(); +    /// # +    /// let mut dependency_history = DependencyHistory::new(); +    /// +    /// dependency_history.push::<EventHandler>(); +    /// +    /// di_container.get_bound::<Button>( +    ///     dependency_history, +    ///     BindingOptions::new().name("huge_red"), +    /// )?; +    /// # +    /// # Ok(()) +    /// # } +    /// ```      fn get_bound<Interface>(          self: &Rc<Self>,          dependency_history: DependencyHistory, -        name: Option<&'static str>, +        binding_options: BindingOptionsWithLt,      ) -> Result<SomePtr<Interface>, DIContainerError>      where          Interface: 'static + ?Sized;  } +#[cfg(not(test))] +pub(crate) type BindingOptionsWithLt<'a> = BindingOptions<'a>; + +#[cfg(test)] +pub(crate) type BindingOptionsWithLt = BindingOptions<'static>; +  /// Blocking dependency injection container.  pub struct DIContainer  { @@ -144,7 +186,7 @@ impl IDIContainer for DIContainer      where          Interface: 'static + ?Sized,      { -        self.get_bound::<Interface>(DependencyHistory::new(), None) +        self.get_bound::<Interface>(DependencyHistory::new(), BindingOptions::new())      }      fn get_named<Interface>( @@ -154,20 +196,24 @@ impl IDIContainer for DIContainer      where          Interface: 'static + ?Sized,      { -        self.get_bound::<Interface>(DependencyHistory::new(), Some(name)) +        self.get_bound::<Interface>( +            DependencyHistory::new(), +            BindingOptions::new().name(name), +        )      } -    #[doc(hidden)]      fn get_bound<Interface>(          self: &Rc<Self>,          dependency_history: DependencyHistory, -        name: Option<&'static str>, +        binding_options: BindingOptions,      ) -> Result<SomePtr<Interface>, DIContainerError>      where          Interface: 'static + ?Sized,      { -        let binding_providable = -            self.get_binding_providable::<Interface>(name, dependency_history)?; +        let binding_providable = self.get_binding_providable::<Interface>( +            binding_options.name, +            dependency_history, +        )?;          #[cfg(feature = "factory")]          return self.handle_binding_providable(binding_providable); @@ -270,7 +316,7 @@ impl DIContainer      fn get_binding_providable<Interface>(          self: &Rc<Self>, -        name: Option<&'static str>, +        name: Option<&str>,          dependency_history: DependencyHistory,      ) -> Result<Providable<Self>, DIContainerError>      where @@ -283,7 +329,7 @@ impl DIContainer                  || {                      Err(DIContainerError::BindingNotFound {                          interface: type_name::<Interface>(), -                        name, +                        name: name.as_ref().map(ToString::to_string),                      })                  },                  Ok, diff --git a/src/di_container/mod.rs b/src/di_container/mod.rs index 5820bc8..63733f5 100644 --- a/src/di_container/mod.rs +++ b/src/di_container/mod.rs @@ -6,5 +6,38 @@ pub mod asynchronous;  pub mod blocking; +/// DI container binding options. +/// +/// # Examples +/// ``` +/// # use syrette::di_container::BindingOptions; +/// # +/// BindingOptions::new().name("foo"); +/// ``` +#[derive(Debug, Default, Clone)] +pub struct BindingOptions<'a> +{ +    name: Option<&'a str>, +} + +impl<'a> BindingOptions<'a> +{ +    /// Returns a new `BindingOptions`. +    #[must_use] +    pub fn new() -> Self +    { +        Self { name: None } +    } + +    /// Returns `Self` with the specified name set. +    #[must_use] +    pub fn name(mut self, name: &'a str) -> Self +    { +        self.name = Some(name); + +        self +    } +} +  // Private.  pub(crate) mod binding_storage;  | 
