Skip to content

tobni/inject-rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GitHub Workflow Status Crates.io GitHub release (latest by date) API

Experimental IOC library inspired by injector for Rust. Goals: IOC + ergonomics.

See test suite for all supported usages.

Examples

using #[inject], call!, get! and container!.

  1. Configure a container, add some provider, e.g an Arc

    use std::sync::Arc;
    
    use ::inject::{container, get, inject};
    
    struct Instance(pub isize);
    
    impl Instance {
        #[inject]
        fn new(a: isize) -> Self {
            Instance(a)
        }
    }
    
    fn main() {
        let provider = Arc::new(Instance(3));
    
        // Install the Arc as a reference provider, anytime using get!
        // will resolve to a reference of this Arc.
        let container = container![ref provider];
    
        let instance: &Instance = get!(&container, &Instance).unwrap();
    
        assert_eq!(3, instance.0)
    }
  2. Let the container resolve a dependency, using a closure as provider

    use ::inject::{Container, container, get, inject};
    
    struct Instance(pub isize);
    
    impl Instance {
        #[inject]
        fn new(a: isize) -> Self {
            Instance(a)
        }
    }
    
    struct Service {
        a: Instance,
    }
    
    impl Service {
        #[inject]
        fn new(instance: Instance) -> Self {
            Self { a: instance }
        }
    }
    
    fn main() {
        // Install a provider, this time a closure returning a value
        let container = container![|container: &Container| Ok(Instance(2))];
    
        let service: Service = get!(&container, Service).unwrap();
    
        assert_eq!(service.a.0, 2)
    }
  3. Sometimes, calling a function with injection is useful,

    use ::inject::{call, Container, container, inject};
    
    struct Service(isize);
    
    impl Service {
        #[inject]
        fn new() -> Self {
            Self(0)
        }
    }
    
    #[inject]
    fn acts_on_service(service: Service) -> isize {
        2 + service.0
    }
    
    fn main() {
        let container = container![|container: &Container| Ok(Service(3))];
    
        let result = call!(&container, acts_on_service).unwrap();
    
        assert_eq!(result, 5)
    }
  4. call! supports a kwarg-flavored syntax

    use ::inject::{call, container, inject};
    
    struct Service(isize);
    
    impl Service {
        #[inject]
        fn new() -> Self {
            Self(0)
        }
    }
    
    #[inject]
    fn acts_on_service(service: Service) -> isize {
        2 + service.0
    }
    
    fn main() {
        let container = container![];
    
        let result = call!(&container, acts_on_service, kwargs = { service: Service(2) }).unwrap();
    
        assert_eq!(result, 4)
    }
  5. Dependency resolution can rely upon a type implementing the Default trait

    use inject::{container, get};
    
    #[derive(Default)]
    struct Service(isize);
    
    fn main() {
        let container = container![];
    
        let service = get!(&container, Service).unwrap();
    
        assert_eq!(service.0, 0)
    }

Details

The get! macro with a container resolves a type in order of: installed provider (1), calling the associated inject function (often generated with #[inject]) function on a type (2), and lastly the Default trait (3).

(2) & (3) can be opt-out by attribute #[inject(no_inject(arg))], (name tbd) in which case only container held provider will be used for resolution of the type. Method specific defaults are annotated as #[inject(defualt(arg = expression))] where expression will lazy evaluate on failing attempt at (1) and (2).

Todo:

  1. Support kwargs for "constructors" with a create_object! flavored macro.
  2. Make #[inject] support Struct attribute notation with #[inject(..)] for individual struct fields.
  3. Make default and no_inject story less annoying.

About

Injection library for Rust

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages