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
//! # Getting started with submodules
//! This guide assumes you have already read the general [getting started guide].
//!
//! [`Module`]s can contain other modules, called submodules. For example, a
//! top-level `RootModule` may use an `AuthModule` to provide authentication
//! services. The submodule's implementation may be known, or the submodule may
//! be hidden behind a trait (aka module interface).
//!
//! ## Why use submodules?
//! Unlike components or providers, the implementation of a submodule does not need to be known to
//! the module. You can easily swap out, say, an OAuth authenticaion implementation for a fake
//! during development. This is more powerful than overriding components/providers because with
//! overriding you cannot remove services from the dependency graph. For example, the OAuth
//! `AuthManager` implementation may use an `OAuthKeyStore` internally. When you swap the module out
//! for a fake, the `OAuthKeyStore` is no longer part of the dependency graph. If the `AuthManager`
//! was instead overridden, the keystore would still be created or would need to be overridden as
//! well, despite being internal or private to the OAuth `AuthManager`.
//!
//! ## The example
//! ```rust
//! use shaku::{module, Component, HasComponent, Interface};
//! use std::sync::Arc;
//!
//! trait MyComponent: Interface {}
//! trait AuthManager: Interface {}
//! trait AuthModule: HasComponent<dyn AuthManager> {}
//!
//! #[derive(Component)]
//! #[shaku(interface = MyComponent)]
//! struct MyComponentImpl {
//!     #[shaku(inject)]
//!     auth_manager: Arc<dyn AuthManager>
//! }
//! impl MyComponent for MyComponentImpl {}
//!
//! module! {
//!     RootModule {
//!         components = [MyComponentImpl],
//!         providers = [],
//!
//!         use AuthModule {
//!             components = [AuthManager],
//!             providers = []
//!         }
//!     }
//! }
//! # fn main() {}
//! ```
//!
//! In this example, `RootModule` knows the implementation of its `MyComponent` component, but it
//! does not know the implementation of `AuthManager` or the `AuthModule` that it gets it from. The
//! `AuthModule` implementation is passed in when `RootModule` is built.
//!
//! ## Providing submodule implementations
//! To build a module, you need to give it a reference to each submodule implementation. The
//! [`module`][module macro] macro will generate a `builder` function which takes in the submodules
//! and outputs a [`ModuleBuilder`]
//!
//! ```rust
//! # use shaku::{module, Component, HasComponent, Interface};
//! # use std::sync::Arc;
//! #
//! # trait MyComponent: Interface {}
//! # trait AuthManager: Interface {}
//! # trait AuthModule: HasComponent<dyn AuthManager> {}
//! #
//! # #[derive(Component)]
//! # #[shaku(interface = MyComponent)]
//! # struct MyComponentImpl { #[shaku(inject)] auth_manager: Arc<dyn AuthManager> }
//! # impl MyComponent for MyComponentImpl {}
//! #
//! # module! {
//! #     RootModule {
//! #         components = [MyComponentImpl], providers = [],
//! #         use AuthModule { components = [AuthManager], providers = [] }
//! #     }
//! # }
//! #
//! #[derive(Component)]
//! #[shaku(interface = AuthManager)]
//! struct AuthManagerImpl;
//! impl AuthManager for AuthManagerImpl {}
//!
//! module! {
//!     AuthModuleImpl: AuthModule {
//!         components = [AuthManagerImpl],
//!         providers = []
//!     }
//! }
//!
//! # fn main() {
//! let auth_module = Arc::new(AuthModuleImpl::builder().build());
//! let root_module = RootModule::builder(auth_module).build();
//!
//! let my_component: &dyn MyComponent = root_module.resolve_ref();
//! # }
//! ```
//!
//! `AuthModuleImpl` has no submodules, thus its `builder` function has no arguments.
//! `RootModule` has one submodule, thus its `builder` function takes in an
//! `Arc<dyn AuthModule>`.
//!
//! Note: `AuthModuleImpl` uses a feature of the [`module`][module macro] macro to automatically
//! implement `AuthModule`. It does this by adding `: AuthModule` after the name of the module.
//! This is shorthand for the statement `impl AuthModule for AuthModuleImpl {}`.
//!
//! [getting started guide]: ../index.html
//! [`Module`]: ../../trait.Module.html
//! [module macro]: ../../macro.module.html
//! [`ModuleBuilder`]: ../../struct.ModuleBuilder.html