Reputation: 5980
I'm really interested in the Dependency Injection pattern as designed / talked about by the pointfree.co guys, where you have an Environment
struct that holds mutable properties of all dependencies.
In short, this pattern:
struct Environment {
var analytics = Analytics()
var date: () -> Date = Date.init
var gitHub = GitHub()
}
var Current = Environment()
You can see their basic example here, and a bigger one here.
What I am trying to do though, is to be able to have dependencies that need dependencies. For example, an Analytics tracker that needs a Network provider to post some data.
import Foundation
// MARK: - NetworkProvider
struct NetworkProvider {
var postData = { (data: Data) in
print("Data posted using the `NetworkProvider`")
}
}
extension NetworkProvider {
static let mock = NetworkProvider(
postData: { data in
print("Mock post!")
}
)
}
// MARK: - Tracker
struct Tracker {
var networkProvider = NetworkProvider()
var track = { (event: String) in
print("Tracked: \(event)")
let data = event.data(using: .utf8)!
networkProvider.postData(data) // <- ERROR
}
}
extension Tracker {
static let mock = Tracker(
networkProvider: .mock,
track: { event in
print("Mocked tracked: \(event)")
}
)
}
// MARK: - Environment
struct Environment {
var networkProvider = NetworkProvider()
var tracker = Tracker()
}
extension Environment {
static let mock = Environment(
networkProvider: .mock,
tracker: .mock
)
}
The code above doesn't compile: Instance member 'networkProvider' cannot be used on type 'Tracker'
, which makes total sense. I can turn the networkProvider
property into a static var
but then I can no longer pass in a mock version, so that's not helpful.
How would I be able to use this method of Dependency Injection, while making it possible to have dependencies that need dependencies?
Upvotes: 1
Views: 596
Reputation: 52118
You can’t access self
in a computed property directly but it is possible if you declare it as a lazy
variable
lazy var track = { [self] (event: String) in ...
Upvotes: 3