InjectPropertyWrapper 0.3.0

InjectPropertyWrapper 0.3.0

Peter Verhage 维护。



  • Peter Verhage

InjectPropertyWrapper

提供了一个通用的 Swift `@Inject` 属性包装器,可以用于从您选择的依赖注入(DI)框架中注入对象/服务。

基本用法

首先,您需要为您使用的依赖注入(DI)框架实现 Resolver 协议。

例如,当使用 Swinject

extension Container: InjectPropertyWrapper.Resolver {
}

在 Swinject 的情况下,Container 类已经包含了一个与 InjectPropertyWrapper `Resolver` 协议所需签名相同的方法(resolve<T>(_ type: T, name: String?))。

然后您需要设置全局解析器(例如在您的应用程序代理中)

let container = Container()
InjectSettings.resolver = container

在容器中注册一些对象

container.register(APIClient.self) { _ in APIClient() }
container.register(MovieRepository.self) { _ in IMDBMovieRepository() }
container.register(MovieRepository.self, name: "netherlands") { _ in IMDBMovieRepository("nl") }

现在您可以使用 @Inject 属性包装器在您的自己的类中注入对象/服务

class IMDBMovieRepository: MovieRepository {
    @Inject private var apiClient: APIClient
    
    ...
    
    func fetchTop10(completionHandler: @escaping (movies: [Movie]) -> Void) {
        ...
    }
}

class MovieViewModel: BindableObject {
    public var didChange = PassthroughSubject<Void, Never>()
    public private(set) var top10: [Movie]? {
        didSet {
            didChange.send()    
        }
    }

    @Inject private var movieRepository: MovieRepository
    
    func load() {
        movieRepository.fetchTop10() { [weak self] movies in
            self?.top10 = movies
        }
    }
}

您也可以使用名称参数注入不同类型的对象

class MovieViewModel: BindableObject {
    ...
    @Inject private var globalMovieRepository: MovieRepository
    @Inject(name: "netherlands") private var nlMovieRepository: MovieRepository
    ...
}

通常,如果属性包装器无法解析依赖项,它将引发一个不可恢复的致命错误。如果出于某种原因您预期容器中有时对象不可用,您可以将属性标记为可选

class MovieViewModel: BindableObject {
    ...
    @Inject(name: "germany") private var deMovieRepository: MovieRepository?
    ...
}

测试

要运行此包的测试,请确保将环境变量 ENABLE_TESTS 设置为 1true。例如,当使用命令行时

ENABLE_TESTS=1 swift test

这允许包在测试时只加载某些依赖项。

许可证

本工程项目遵循MIT许可证条款。请参阅LICENSE文件。