4 个版本

0.1.3 2020 年 8 月 21 日
0.1.2 2020 年 8 月 16 日
0.1.1 2020 年 8 月 16 日
0.1.0 2020 年 8 月 14 日

#381配置

每月 42 次下载

自定义许可证

28KB
352

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

injector 启发的 Rust 实验性 IOC 库。目标:IOC + 人体工程学。

查看所有支持的用法,请参阅 测试套件

示例

使用 #[inject]call!get!container!

  1. 配置一个容器,添加一些提供者,例如一个 Arc

    use std::sync::Arc;
    
    use ::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. 让容器解析一个依赖项,使用闭包作为提供者

    use ::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. 有时,使用注入调用函数很有用,

    use ::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! 支持类似 kwarg 的语法

    use ::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. 依赖项解析可以依赖于实现 Default 特性的类型

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

详细信息

带有 containerget! 宏按照以下顺序解析类型:已安装的提供者(1),在类型上调用相关的 inject 函数(通常通过 #[inject])函数(2),最后是 Default 特性(3)。

(2) & (3) 可以通过属性 #[inject(no_inject(arg))](名称待定)取消选择,在这种情况下,仅容器持有的提供者将用于解析类型。方法特定默认值注释为 #[inject(defualt(arg = 表达式))],其中表达式将在 (1) 和 (2) 失败尝试时延迟评估。

待办事项

  1. 支持 "构造函数" 的 kwarg,使用 create_object! 风格的宏。
  2. 使 #[inject] 支持结构体属性符号,使用 #[inject(..)] 对单个结构体字段进行注入。
  3. 使 defaultno_inject 故事更加不令人烦恼。

依赖项

~1.5MB
~35K SLoC