通过属性包装器崩溃的嵌套依赖注入
Posted
技术标签:
【中文标题】通过属性包装器崩溃的嵌套依赖注入【英文标题】:Nested dependency injection through Property wrapper crashes 【发布时间】:2020-04-20 06:44:34 【问题描述】:关注this 一切正常。
但是当我尝试用同样的方法解决嵌套依赖项时(依赖注入的类又具有依赖项——在我们的例子中是 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] = ["***", 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 "***"
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”返回表达式求值前的状态。
【问题讨论】:
【参考方案1】:我还在使用属性包装器在 Swift 5.1 中搜索 Dependency Injection
。
这对我有用 - 它与您的解决方案非常相似,并且非常适合嵌套依赖项:
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
完整的解释可以在here找到。
【讨论】:
以上是关于通过属性包装器崩溃的嵌套依赖注入的主要内容,如果未能解决你的问题,请参考以下文章