Struct runtime_injector::Injector[][src]

pub struct Injector { /* fields omitted */ }
Expand description

A runtime dependency injection container. This holds all the bindings between service types and their providers, as well as all the mappings from interfaces to their implementations (if they differ).

Injecting the injector

Cloning the injector does not clone the providers inside of it. Instead, both injectors will use the same providers, meaning that an injector can be passed to a service as a dependency. The injector can be requested as itself without using a service pointer. It does not need to be registered as a dependency in the builder beforehand.

Note that requesting the injector inside of your services is generally bad practice, and is known as the service locator antipattern. This is mostly useful for custom ad-hoc service factories where you can create instances of your services on demand. If you need to create instances of a service outside of your constructor, you may want to use Factory<R> instead.

use runtime_injector::{
    constant, InjectResult, Injector, IntoSingleton, IntoTransient, Svc,
};
use std::sync::Mutex;

struct FloatFactory(Injector);

impl FloatFactory {
    pub fn get(&self) -> InjectResult<f32> {
        let int: Box<i32> = self.0.get()?;
        Ok(*int as f32)
    }
}

fn count(counter: Svc<Mutex<i32>>) -> i32 {
    let mut counter = counter.lock().unwrap();
    *counter += 1;
    *counter
}

let mut builder = Injector::builder();
builder.provide(constant(Mutex::new(0i32)));
builder.provide(count.transient());
builder.provide(FloatFactory.singleton());

let injector = builder.build();
let float_factory: Svc<FloatFactory> = injector.get().unwrap();
let value1 = float_factory.get().unwrap();
let value2 = float_factory.get().unwrap();

assert_eq!(1.0, value1);
assert_eq!(2.0, value2);

Implementations

impl Injector[src]

#[must_use]
pub fn builder() -> InjectorBuilder
[src]

Creates a builder for an injector. This is the preferred way of creating an injector.

#[must_use]
pub fn new(
    providers: HashMap<ServiceInfo, Option<Vec<Box<dyn Provider>>>>
) -> Self
[src]

👎 Deprecated since 0.3.1:

prefer using a builder; this will be removed in 0.5

Creates a new injector directly from its providers and implementations. Prefer Injector::builder() for creating new injectors instead.

pub fn get<R: Request>(&self) -> InjectResult<R>[src]

Performs a request for a service. There are several types of requests that can be made to the service container by default:

  • Svc<T>: Requests a service pointer to the given interface and creates an instance of the service if needed. If multiple service providers are registered for that interface, then returns an error instead.
  • Box<T>: Requests an owned service pointer to the given interface and creates an instance of the service. Not all service providers can provide owned versions of their services, so this may fail for some services.
  • Option<Svc<T>>/Option<Box<T>>: Requests a service pointer to the given interface and creates an instance of the service if needed. If no provider for that service is registered, then returns Ok(None) rather than returning an error. If multiple providers are registered, then instead returns an error. If an owned pointer is requested but the provider can’t provide owned pointers, then returns an error.
  • Vec<Svc<T>>/Vec<Box<T>>: Requests all the implementations of an interface. This will eagerly create the services as part of the request. If owned service pointers are requested and any providers can’t provide owned pointers, then returns an error instead.
  • Services<T>: Requests all the implementations of an interface. This will lazily create the services on demand. See the documentation for Services<T> for more details.
  • Injector: Requests a clone of the injector. While it doesn’t make much sense to request this directly from the injector itself, this allows the injector to be requested as a dependency inside of services (for instance, factories).
  • RequestInfo: Requests information about the current request, including the current resolution path.
  • Factory<R>: Lazily performs requests on demand.

See the documentation for Request for more information on what can be requested. Custom request types can also be created by implementing Request on your type.

Requests to service pointers of sized types will attempt to use the registered provider to retrieve an instance of that service. For instance, a request for a singleton service will create an instance of that service if one doesn’t exist already, and either return a service pointer to the instance that was already created, or return a service pointer to the new instance (if one didn’t exist already).

use runtime_injector::{Injector, IntoSingleton, Svc};

#[derive(Default)]
struct Bar;

let mut builder = Injector::builder();
builder.provide(Bar::default.singleton());

let injector = builder.build();
let _bar: Svc<Bar> = injector.get().unwrap();

Requests for service pointers of dyn Trait interface types will instead request the implementation of that interface type. For example, if dyn Foo’s registered implementation is for the service type Bar, then a request for a service pointer of dyn Foo will return a service pointer to a Bar, although the return type will be Svc<dyn Foo>.

use runtime_injector::{
    interface, Injector, IntoSingleton, Svc, TypedProvider,
};

trait Foo: Send + Sync {}
interface!(dyn Foo = [Bar]);

#[derive(Default)]
struct Bar;
impl Foo for Bar {}

let mut builder = Injector::builder();
builder.provide(Bar::default.singleton().with_interface::<dyn Foo>());

let injector = builder.build();
let _bar: Svc<dyn Foo> = injector.get().unwrap();

If multiple providers for a service exist, then a request for a single service pointer to that service will fail.

use runtime_injector::{
    interface, Injector, IntoSingleton, Svc, TypedProvider,
};

trait Foo: Send + Sync {}
interface!(dyn Foo = [Bar, Baz]);

#[derive(Default)]
struct Bar;
impl Foo for Bar {}

#[derive(Default)]
struct Baz;
impl Foo for Baz {}

let mut builder = Injector::builder();
builder.provide(Bar::default.singleton().with_interface::<dyn Foo>());
builder.provide(Baz::default.singleton().with_interface::<dyn Foo>());

let injector = builder.build();
assert!(injector.get::<Svc<dyn Foo>>().is_err());

pub fn get_with<R: Request>(
    &self,
    request_info: &RequestInfo
) -> InjectResult<R>
[src]

Performs a request for a service with additional request information.

Example

use runtime_injector::{
    Injector, IntoTransient, Request, RequestInfo, Svc,
};

struct Foo(String);
impl Foo {
    fn new(request_info: RequestInfo) -> Self {
        let value = request_info
            .get_parameter("value")
            .unwrap()
            .downcast_ref::<String>()
            .unwrap()
            .clone();
        Foo(value)
    }
}

let mut builder = Injector::builder();
builder.provide(Foo::new.transient());

let injector = builder.build();
let mut request_info = RequestInfo::default();
request_info.insert_parameter("value", "foo".to_owned());

let foo: Svc<Foo> = injector.get_with(&request_info).unwrap();
assert_eq!("foo", foo.0);

Trait Implementations

impl Clone for Injector[src]

fn clone(&self) -> Injector[src]

Returns a copy of the value. Read more

fn clone_from(&mut self, source: &Self)1.0.0[src]

Performs copy-assignment from source. Read more

impl Default for Injector[src]

fn default() -> Injector[src]

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

impl Request for Injector[src]

Requests the injector used to resolve services.

fn request(injector: &Injector, _info: &RequestInfo) -> InjectResult<Self>[src]

Performs the request to the injector.

Auto Trait Implementations

impl !RefUnwindSafe for Injector

impl Send for Injector

impl Sync for Injector

impl Unpin for Injector

impl !UnwindSafe for Injector

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

pub fn type_id(&self) -> TypeId[src]

Gets the TypeId of self. Read more

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

pub fn borrow(&self) -> &T[src]

Immutably borrows from an owned value. Read more

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

pub fn borrow_mut(&mut self) -> &mut T[src]

Mutably borrows from an owned value. Read more

impl<T> From<T> for T[src]

pub fn from(t: T) -> T[src]

Performs the conversion.

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

pub fn into(self) -> U[src]

Performs the conversion.

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

pub fn to_owned(&self) -> T[src]

Creates owned data from borrowed data, usually by cloning. Read more

pub fn clone_into(&self, target: &mut T)[src]

🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

Uses borrowed data to replace owned data, usually by cloning. Read more

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>[src]

Performs the conversion.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

pub fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>[src]

Performs the conversion.