swift - 通过属性包装器崩溃的嵌套依赖注入
问题描述
按照这个它工作正常。
但是,当我尝试用同样的方法解决嵌套依赖项时(依赖注入的类又具有依赖项——在我们的例子中是 NetworkService),它崩溃了。我在这里做错了什么?任何帮助将不胜感激。
实时场景
class AppContainer {
static let shared = AppContainer()
var index: [Any] = [NetworkingLibrary(), NetworkService()]
func resolve<T>(_ type: T.Type) -> T {
return index.first(where: { $0 as? T != nil }) as! T
}
}
@propertyWrapper
struct Inject<Value> {
var value: Value
var wrappedValue: Value {
get {
return value
}
set {
value = newValue
}
}
init(_ container: AppContainer = AppContainer.shared) {
value = container.resolve(Value.self)
}
}
class UserService {
@Inject() var networkLayer: NetworkLayer
init() { }
func fetchUsers() {
networkLayer.fetchData()
}
}
class PostService {
@Inject() var networkLayer: NetworkLayer
init() { }
func fetchPosts() {
networkLayer.fetchData()
}
}
protocol NetworkLayer {
func fetchData()
}
class NetworkService: NetworkLayer {
@Inject() var networkLibrary: NetworkingLibraryProtocol //Expecting networkLibrary to be resolved to NetworkingLibrary()
func fetchData() {
networkLibrary.fetch()
print("Fetching Data")
}
}
let postService = PostService() // crashes here
postService.fetchPosts()
let userService = UserService() // crashes here
userService.fetchUsers()
你可以在操场上运行的代码
class AppContainer {
static let shared = AppContainer()
var index: [Any] = ["StackOverflow", NetworkService()]
func resolve<T>(_ type: T.Type) -> T {
return index.first(where: { $0 as? T != nil }) as! T
}
}
@propertyWrapper
struct Inject<Value> {
var value: Value
var wrappedValue: Value {
get {
return value
}
set {
value = newValue
}
}
init(_ container: AppContainer = AppContainer.shared) {
value = container.resolve(Value.self)
}
}
class UserService {
@Inject() var networkLayer: NetworkLayer
init() { }
func fetchUsers() {
networkLayer.fetchData()
}
}
class PostService {
@Inject() var networkLayer: NetworkLayer
init() { }
func fetchPosts() {
networkLayer.fetchData()
}
}
protocol NetworkLayer {
func fetchData()
}
class NetworkService: NetworkLayer {
@Inject() var str: String // Expecting str to be resolved to "StackOverflow"
func fetchData() {
print(str)
print("Fetching Data")
}
}
let postService = PostService()
postService.fetchPosts()
let userService = UserService()
userService.fetchUsers()
崩溃日志:-
错误:执行被中断,原因:EXC_BAD_INSTRUCTION(代码=EXC_I386_INVOP,子代码=0x0)。进程一直停留在被中断的地方,使用“thread return -x”返回表达式求值前的状态。
解决方案
我还在Dependency Injection
使用属性包装器在 Swift 5.1 中搜索。
这对我有用 - 它与您的解决方案非常相似,并且非常适合嵌套依赖项:
enum Dependencies {
struct Name: Equatable {
let rawValue: String
static let `default` = Name(rawValue: "__default__")
static func == (lhs: Name, rhs: Name) -> Bool { lhs.rawValue == rhs.rawValue }
}
final class Container {
private var dependencies: [(key: Dependencies.Name, value: Any)] = []
static let `default` = Container()
func register(_ dependency: Any, for key: Dependencies.Name = .default) {
dependencies.append((key: key, value: dependency))
}
func resolve<T>(_ key: Dependencies.Name = .default) -> T {
return (dependencies
.filter { (dependencyTuple) -> Bool in
dependencyTuple.key == key
&& dependencyTuple.value is T
}
.first)?.value as! T
}
}
@propertyWrapper
struct Inject<T> {
private let dependencyName: Name
private let container: Container
var wrappedValue: T { container.resolve(dependencyName) }
init(_ dependencyName: Name = .default, on container: Container = .default) {
self.dependencyName = dependencyName
self.container = container
}
}
}
这就是您在代码中使用它的方式:
Dependencies.Container.default.register(NetworkService())
Dependencies.Container.default.register(TransactionRepository())
Dependencies.Container.default.register(TransactionService())
class TransactionService {
@Dependencies.Inject() private var networkService: NetworkService
@Dependencies.Inject() private var transactionRepository: TransactionRepository
}
class SomeOtherService {
@Dependencies.Inject() private var transactionService: TransactionService
}
完整的解释可以在这里找到。
推荐阅读
- javascript - 替换 Foreach -> For
- r - 从数据帧中的二进制和字符变量创建双模网络
- docker - 部署后编辑容器化应用程序的应用程序设置
- windows-terminal - 如何在 Windows 终端中设置重复的选项卡键绑定
- python - Python 多处理一个 For 循环
- awk - 根据系统日期替换特定位置的文本
- python - 从 csv 文件中的城市列添加国家列
- kubernetes - 在具有 haproxy、2 个主节点、1 个节点的 Kubernetes 集群中。当 master1 关闭时,故障转移不起作用
- php - 重定向 POST - 域到 IP
- css - 如何在 styled-components css``中使用动画?