Skip to content

Instantly share code, notes, and snippets.

@arashkashi
Created November 21, 2022 15:46
Show Gist options
  • Save arashkashi/7ffadb7d300655c620bb09cba11260ed to your computer and use it in GitHub Desktop.
Save arashkashi/7ffadb7d300655c620bb09cba11260ed to your computer and use it in GitHub Desktop.
a light weight injection code.
// MARK: Demontration of Usage of Injection system
// 1. First step: make the key object, the current value type is the one you are trying to add to injection system.
private struct BaseClassKey: InjectionKey {
static var currentValue: BaseClass = RealSubClass()
}
// 2. How to inject the currect value
func test() {
var dataController = TestDataStructure()
InjectedValues[\.networkProvider] = MockedSubClass()
dataController.networkProvider = RealSubClass()
dataController.performDataRequest() // prints: Data requested using the 'NetworkProvider'
}
// 3. How to use the currently injected value
struct TestDataStructure {
@Injected(\.networkProvider) var networkProvider: BaseClass
func performDataRequest() {
networkProvider.requestData()
}
}
class BaseClass {
func requestData() {
}
}
class RealSubClass: BaseClass {
override func requestData() {
print("Data requested using the `NetworkProvider`")
}
}
class MockedSubClass: BaseClass {
override func requestData() {
print("Data requested using the `MockedNetworkProvider`")
}
}
// MARK: Implementation of Injection System
public protocol InjectionKey {
/// The associated type representing the type of the dependency injection key's value.
associatedtype Value
/// The default value for the dependency injection key.
static var currentValue: Self.Value { get set }
}
extension InjectedValues {
var networkProvider: BaseClass {
get { Self[BaseClassKey.self] }
set { Self[BaseClassKey.self] = newValue }
}
}
/// Provides access to injected dependencies.
struct InjectedValues {
/// This is only used as an accessor to the computed properties within extensions of `InjectedValues`.
private static var current = InjectedValues()
/// A static subscript for updating the `currentValue` of `InjectionKey` instances.
static subscript<K>(key: K.Type) -> K.Value where K : InjectionKey {
get { key.currentValue }
set { key.currentValue = newValue }
}
/// A static subscript accessor for updating and references dependencies directly.
static subscript<T>(_ keyPath: WritableKeyPath<InjectedValues, T>) -> T {
get { current[keyPath: keyPath] }
set { current[keyPath: keyPath] = newValue }
}
}
@propertyWrapper
struct Injected<T> {
private let keyPath: WritableKeyPath<InjectedValues, T>
var wrappedValue: T {
get { InjectedValues[keyPath] }
set { InjectedValues[keyPath] = newValue }
}
init(_ keyPath: WritableKeyPath<InjectedValues, T>) {
self.keyPath = keyPath
}
}
@arashkashi
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment