Skip to content

Instantly share code, notes, and snippets.

@IuriiIaremenko
Last active September 4, 2022 10:56
Show Gist options
  • Save IuriiIaremenko/7a3b8655e8f426adb0778b480c33e5f1 to your computer and use it in GitHub Desktop.
Save IuriiIaremenko/7a3b8655e8f426adb0778b480c33e5f1 to your computer and use it in GitHub Desktop.
Swift Dependency Injection via Property Wrapper
//
// Inject.swift
//
// Created by Iurii Iaremenko on 11.01.2020.
//
import Foundation
@propertyWrapper
public class Inject<Value> {
private let name: String?
private var storage: Value?
public var wrappedValue: Value {
storage ?? {
let value: Value = Dependencies.root.resolve(for: name)
storage = value
return value
}()
}
public init() {
self.name = nil
}
public init(_ name: String) {
self.name = name
}
}
final class Dependencies {
static let root = Dependencies()
private var factories = [String: () -> Any]()
private var inited = [Any]()
private init() {
setupDependencies()
}
func add<T>(_ factory: @autoclosure @escaping () -> T) {
let key = String(describing: T.self)
factories[key] = factory
}
func resolve<T>(for name: String? = nil) -> T {
if let component: T = inited.first(where: { $0 is T }) as? T {
return component
}
let name = name ?? String(describing: T.self)
guard let component: T = factories[name]?() as? T else {
fatalError("Dependency '\(T.self)' not resolved!")
}
inited.append(component)
return component
}
}
extension Dependencies {
/// Important: all dependencies must be registered here
func setupDependencies() {
add(Service())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment