2个版本

0.1.1 2020年8月21日
0.1.0 2020年8月14日

#34 in #inject

50 每月下载
用于 inject

自定义许可

33KB
1K SLoC

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! 支持类似关键字参数的语法

    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)
    }
    

详细信息

get! 宏与 container 结合,按以下顺序解析类型:已安装提供者(1)、在类型上调用关联的 #[inject] 函数(通常通过 #[inject] 生成)(2),最后是 Default 特性(3)。

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

待办事项

  1. 支持具有 create_object! 风格宏的 "构造函数" 的 kwargs。
  2. 使 #[inject] 支持 Struct 属性标记,使用 #[inject(...)] 为单个结构体字段。
  3. 使 defaultno_inject 更加不烦人。

依赖关系

~1.5MB
~35K SLoC