1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
//! This module contains trait definitions for components and interfaces use crate::module::ModuleInterface; use crate::Module; use crate::ModuleBuildContext; use std::any::Any; use std::sync::Arc; /// Components provide a service by implementing an interface. They may use /// other components as dependencies. /// /// This trait is normally derived, but if the `derive` feature is turned off /// then it will need to be implemented manually. pub trait Component<M: Module>: Interface { /// The trait/interface which this component implements type Interface: Interface + ?Sized; /// The parameters this component requires. If none are required, use `()`. #[cfg(feature = "thread_safe")] type Parameters: Default + Send; /// The parameters this component requires. If none are required, use `()`. #[cfg(not(feature = "thread_safe"))] type Parameters: Default; /// Use the build context and parameters to create the component. Other /// components can be resolved by adding a [`HasComponent`] bound to the /// `M` generic, then calling [`M::build_component`]. /// /// [`HasComponent`]: trait.HasComponent.html /// [`M::build_component`]: trait.HasComponent.html#tymethod.build_component fn build(context: &mut ModuleBuildContext<M>, params: Self::Parameters) -> Box<Self::Interface>; } #[cfg(not(feature = "thread_safe"))] trait_alias!( /// Interfaces must be `'static` in order to be stored in a module /// (hence the `Any` requirement). /// /// The `thread_safe` feature is turned off, so interfaces do not need to /// implement `Send` or `Sync`. pub Interface = Any ); #[cfg(feature = "thread_safe")] trait_alias!( /// Interfaces must be `'static` in order to be stored in a module /// (hence the `Any` requirement). /// /// The `thread_safe` feature is turned on, which requires interfaces to /// also implement `Send` and `Sync`. pub Interface = Any + Send + Sync ); /// The type signature of [`Component::build`] without the parameters. This is /// used when overriding a component via [`ModuleBuilder::with_component_override_fn`] /// /// [`Component::build`]: trait.Component.html#tymethod.build /// [`ModuleBuilder::with_component_override_fn`]: struct.ModuleBuilder.html#method.with_component_override_fn #[cfg(not(feature = "thread_safe"))] pub type ComponentFn<M, I> = Box<dyn FnOnce(&mut ModuleBuildContext<M>) -> Box<I>>; /// The type signature of [`Component::build`] without the parameters. This is /// used when overriding a component via [`ModuleBuilder::with_component_override_fn`] /// /// [`Component::build`]: trait.Component.html#tymethod.build /// [`ModuleBuilder::with_component_override_fn`]: struct.ModuleBuilder.html#method.with_component_override_fn #[cfg(feature = "thread_safe")] pub type ComponentFn<M, I> = Box<dyn (FnOnce(&mut ModuleBuildContext<M>) -> Box<I>) + Send + Sync>; /// Indicates that a module contains a component which implements the interface. pub trait HasComponent<I: Interface + ?Sized>: ModuleInterface { /// Build the component during module build. Usually this involves calling /// [`ModuleBuildContext::build_component`] with the implementation. /// /// [`ModuleBuildContext::build_component`]: struct.ModuleBuildContext.html#method.build_component fn build_component(context: &mut ModuleBuildContext<Self>) -> Arc<I> where Self: Module + Sized; /// Get a reference to the component. The ownership of the component is /// shared via `Arc`. /// /// # Example /// ``` /// # use shaku::{module, Component, Interface, HasComponent}; /// # use std::sync::Arc; /// # /// # trait Foo: Interface {} /// # /// # #[derive(Component)] /// # #[shaku(interface = Foo)] /// # struct FooImpl; /// # impl Foo for FooImpl {} /// # /// # module! { /// # TestModule { /// # components = [FooImpl], /// # providers = [] /// # } /// # } /// # /// # fn main() { /// # let module = TestModule::builder().build(); /// # /// let foo: Arc<dyn Foo> = module.resolve(); /// # } /// ``` fn resolve(&self) -> Arc<I>; /// Get a reference to the component. /// /// # Example /// ``` /// # use shaku::{module, Component, Interface, HasComponent}; /// # use std::sync::Arc; /// # /// # trait Foo: Interface {} /// # /// # #[derive(Component)] /// # #[shaku(interface = Foo)] /// # struct FooImpl; /// # impl Foo for FooImpl {} /// # /// # module! { /// # TestModule { /// # components = [FooImpl], /// # providers = [] /// # } /// # } /// # /// # fn main() { /// # let module = TestModule::builder().build(); /// # /// let foo: &dyn Foo = module.resolve_ref(); /// # } /// ``` fn resolve_ref(&self) -> &I; }