Struct teloc::ServiceProvider[][src]

pub struct ServiceProvider<Parent, Conts> { /* fields omitted */ }
Expand description

ServiceProvider struct is used as an IoC-container in which you declare your dependencies.

Algorithm for working in ServiceProvider is:

  1. Create an empty by ServiceProvider::new function.
  2. Declare your dependencies using add_* methods (more about theirs read below).
  3. Fork ServiceProvider when you need working with scoped sessions (like when you processing web request).
  4. Get needed dependencies from container using Resolver::resolve trait.

If you do not register all of needed dependencies, then compiler do not compile your code. If error puts you into a stupor, read our manual about how read errors.

Example of usage ServiceProvider:

use std::rc::Rc;
use teloc::*;

struct ConstService {
    number: Rc<i32>,
}

#[inject]
impl ConstService {
    pub fn new(number: Rc<i32>) -> Self {
        ConstService { number }
    }
}

#[derive(Dependency)]
struct Controller {
    number_service: ConstService,
}

let container = ServiceProvider::new()
    .add_transient::<ConstService>()
    .add_transient::<Controller>();
let scope = container.fork().add_instance(Rc::new(10));
let controller: Controller = scope.resolve();
assert_eq!(*controller.number_service.number, 10);

Implementations

Create an empty instance of ServiceProvider

Forking ServiceProvider creates a new ServiceProvider with reference to the parent. resolve method on forked ServiceProvider will find dependencies form self and parent.

Forking ServiceProvider creates a new ServiceProvider with reference to the parent. resolve method on forked ServiceProvider will find dependencies form self and parent.

Forking ServiceProvider creates a new ServiceProvider with reference to the parent. resolve method on forked ServiceProvider will find dependencies form self and parent.

Method used primary for internal actions. In common usage you don’t need to use it. It add dependencies to the store. You need to put in first generic parameter some ContainerElem type. Usage:

use teloc::*;
use teloc::dev::container::TransientContainer;

struct Service {
    data: i32,
}

let sp = ServiceProvider::new()
    ._add::<TransientContainer<Service>>(());

Add dependency with the Transient lifetime. Transient services will be created each time when it called. Use this lifetime for lightweight stateless services.

Can be resolved only by ownership.

Usage:

use teloc::*;
use uuid::Uuid;

struct Service { uuid: Uuid }
#[inject]
impl Service {
    fn new() -> Self { Self { uuid: Uuid::new_v4() } }
}

let sp = ServiceProvider::new()
    .add_transient::<Service>();

let s1: Service = sp.resolve();
let s2: Service = sp.resolve();

assert_ne!(s1.uuid, s2.uuid);

Add dependency with the Singleton lifetime. Singleton services will be created only one time when it will be called first time. It will be same between different calls in parent and forked ServiceProvider

Can be resolved by reference or by cloning. If you wish to clone this dependency then it must implement DependencyClone trait. For more information see DependencyClone trait.

Usage:

use teloc::*;
use uuid::Uuid;

struct Service { uuid: Uuid }
#[inject]
impl Service {
    fn new() -> Self { Self { uuid: Uuid::new_v4() } }
}

let sp = ServiceProvider::new()
    .add_singleton::<Service>();
let scope = sp.fork();

let s1: &Service = sp.resolve();
let s2: &Service = scope.resolve();

assert_eq!(s1.uuid, s2.uuid);

Usage with cloning:

use teloc::*;
use uuid::Uuid;
use std::rc::Rc;

struct Service { uuid: Uuid }
#[inject]
impl Service {
    fn new() -> Self { Self { uuid: Uuid::new_v4() } }
}

let sp = ServiceProvider::new()
    .add_singleton::<Rc<Service>>();

let s1: Rc<Service> = sp.resolve();
let s2: Rc<Service> = sp.resolve();

assert_eq!(s1.uuid, s2.uuid)

Add anything instance to provider. It likes singleton, but it cannot get dependencies from the provider. Use it for adding single objects like configs.

Can be resolved by reference or by cloning. If you wish to clone this dependency then it must implement DependencyClone trait. For more information see DependencyClone trait.

Usage:

use teloc::*;

#[derive(Debug, PartialEq)]
struct Config { token: String, ip: String }

struct Service<'a> { token: &'a str, ip: &'a str }
#[inject]
impl<'a> Service<'a> {
    fn new(config: &'a Config) -> Self { Self { token: &config.token, ip: &config.ip } }
}

let config = Config { token: "1234ABCDE".into(), ip: "192.168.0.1".into() };

let sp = ServiceProvider::new()
    .add_instance(&config)
    .add_transient::<Service>();

let config_ref: &Config = sp.resolve();
let s: Service = sp.resolve();

assert_eq!(&config, config_ref);
assert_eq!(&config_ref.token, s.token);
assert_eq!(&config_ref.ip, s.ip);

Same as ServiceProvider::add_transient, but can be used for convert one type to another when resolving. Can be used for creating Box<dyn Trait> instances, for example.

Suffix _c means ‘convert’.

Usage:

use teloc::*;

trait NumberService {
    fn get_num(&self) -> i32;
}

struct TenService {
    number: i32,
}
impl NumberService for TenService {
    fn get_num(&self) -> i32 {
        self.number
    }
}
#[inject]
impl TenService {
    fn new() -> Self {
        Self { number: 10 }
    }
}
impl From<Box<TenService>> for Box<dyn NumberService> {
    fn from(x: Box<TenService>) -> Self {
        x
    }
}

#[derive(Dependency)]
struct Controller {
    number_service: Box<dyn NumberService>,
}

let container = ServiceProvider::new()
    .add_transient_c::<Box<dyn NumberService>, Box<TenService>>()
    .add_transient::<Controller>();
let controller: Controller = container.resolve();

assert_eq!(controller.number_service.get_num(), 10);

Same as Provider::add_transient_c but for Singleton lifetime.

Same as Provider::add_transient_c but for Instance lifetime.

Trait Implementations

Formats the value using the given formatter. Read more

Returns the “default value” for a type. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Extract a subset of the possible types in a coproduct (or get the remaining possibilities) Read more

Performs the conversion.

Performs the conversion.

Performs the indexed conversion.

Consumes the current HList and returns an HList with the requested shape. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.