Expand description
There are one type can be provider of services: ServiceProvider
. It used as store for dependencies with
Instance
and Singleton
lifetimes, and for declaring all dependencies using .add_*()
methods. It can be forked to
create a local scope with local instances.
There are four lifetimes for dependencies:
Transient
. Service will be created when resolves. Can depend on dependencies with anything lifetime.Singleton
. Service will be created once atServiceProvider
when it resolved (lazy). Can depend on dependencies with anything lifetime. Cannot depend on services from forkedServiceProvider
instances.Instance
. Dependency was created outside ofServiceProvider
and can be used by any other dependency.
How to work:
- Declare your structs.
- Create constructors and add
#[inject]
macro on its. - Create a
ServiceProvider
object. - Add your services and dependencies using
ServiceProvider::add_*
methods. - Fork
ServiceProvider
if you need to create local scope. - Get service from provider using
.resolve()
method. - Work with service.
Example:
use std::rc::Rc;
use teloc_macross::{Dependency, inject};
use telocs::*;
struct ConstService {
number: Rc<i32>,
}
#[inject]
impl ConstService {
pub fn new(number: Rc<i32>) -> Self {
ConstService { number }
}
}
// derive macro can be used when all fields implement `Dependency` trait,
// but we do not recommend use it in production code
#[derive(Dependency)]
struct Controller {
number_service: ConstService,
}
// Create `ServiceProvider` struct that store itself all dependencies
let container = ServiceProvider::new()
// Add dependency with `Singleton` lifetime. More about lifetimes see above.
.add_transient::<ConstService>()
// Add dependency with `Transient` lifetime. More about lifetimes see above.
.add_transient::<Controller>();
// Fork `ServiceProvider`. It creates a new `ServiceProvider` which will have
// access to the dependencies from parent `ServiceProvider`.
let scope = container
// .fork() method creates a local mutable scope with self parent immutable `ServiceProvider`.
.fork()
// Add an instance of `Rc<i32>` that will be used when `ConstService` will be initialized.
.add_instance(Rc::new(10));
let controller: Controller = scope.resolve();
assert_eq!(*controller.number_service.number, 10);
Re-exports§
pub use service_provider::EmptyServiceProvider;
pub use service_provider::SelectContainer;
pub use service_provider::ServiceProvider;
Modules§
Structs§
Traits§
- Container
- Init is a trait used in
ServiceProvider
for create an empty version ofContainer
. If you create your own version of container and you want that it can work with other container likeConvertContainer
, you must implement this trait. - Dependency
- Trait is used to working with
Resolver
trait. If you want that your service can be resolved byResolver
, you may implement this trait for your service. There are three ways: - Dependency
Clone - Trait is used to resolve services by cloning. It must be implement only for wrappers that
guarantees that there are only one instance and many references, like
Rc
,Arc
structs and immutable reference. - GetDependencies
- The trait, used for getting list of dependencies from provider of services. Do not use it by yourself.
- Resolve
Container - Trait needed primary to working with
ConvertContainer
. Implement it for your container if you wish that your container can be placed inside ofConvertContainer
- Resolver
- This trait is used to resolve some object from service provider. Generic
T
used only to avoid absence of specialization and for working of type inference. You must implement it yourself only when you implement your own version of container.
Attribute Macros§
- inject
- Macro can be used on free functions and impls, including impl traits, with only one implement
method. It will generate
Dependency
impl in which calling function that will tagged by this macro. We recommend using this macro in production code.
Derive Macros§
- Dependency
- Derive macro can be used on structs with named fields when all fields implements
Dependency
trait or fields described using#[init(...)]
attr. We do not recommend using this macro in production code.