Last active
August 5, 2022 13:41
-
-
Save sssbohdan/d817e268a2015280b7b5f3b9e02933e5 to your computer and use it in GitHub Desktop.
Resolver
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// DI.swift | |
// MobiusNotes | |
// | |
// Created by bsavych on 05/08/2022. | |
// | |
import Foundation | |
enum DIScope { | |
case singleton | |
case new | |
} | |
protocol DIRegistration { | |
func register<Element>(object: @escaping (DIResolver) -> Element, in scope: DIScope) | |
func register<Element, Param1>(object: @escaping (DIResolver, Param1) -> Element, in scope: DIScope) | |
func register<Element, Param1, Param2>(object: @escaping (DIResolver, Param1, Param2) -> Element, in scope: DIScope) | |
func register<Element, Param1, Param2, Param3>(object: @escaping (DIResolver, Param1, Param2, Param3) -> Element, in scope: DIScope) | |
} | |
protocol DIResolver { | |
func resolve<Element>(type: Element.Type) -> Element | |
func resolve<Element, Param1>(type: Element.Type, param: Param1) -> Element | |
func resolve<Element, Param1, Param2>(type: Element.Type, params: (Param1, Param2)) -> Element | |
func resolve<Element, Param1, Param2, Param3>(type: Element.Type, params: (Param1, Param2, Param3)) -> Element | |
} | |
typealias DIProtocol = DIRegistration & DIResolver | |
final class DI: DIProtocol { | |
private lazy var singletons = [String: Any]() | |
private lazy var functions = [String: Any]() | |
private lazy var scopes = [String: DIScope]() | |
// MARK: - Register | |
func register<Element>(object: @escaping (DIResolver) -> Element, in scope: DIScope) { | |
let string = String(reflecting: Element.self) | |
self.register(object, id: string, scope: scope) | |
} | |
func register<Element, Param1>(object: @escaping (DIResolver, Param1) -> Element, in scope: DIScope) { | |
let string = String(reflecting: Element.self) | |
self.register(object, id: string, scope: scope) | |
} | |
func register<Element, Param1, Param2>(object: @escaping (DIResolver, Param1, Param2) -> Element, in scope: DIScope) { | |
let string = String(reflecting: Element.self) | |
self.register(object, id: string, scope: scope) | |
} | |
func register<Element, Param1, Param2, Param3>(object: @escaping (DIResolver, Param1, Param2, Param3) -> Element, in scope: DIScope) { | |
let string = String(reflecting: Element.self) | |
self.register(object, id: string, scope: scope) | |
} | |
private func register(_ obj: Any, id: String, scope: DIScope) { | |
self.scopes[id] = scope | |
self.functions[id] = obj | |
} | |
// MARK: - Resolve | |
func resolve<Element>(type: Element.Type) -> Element { | |
let string = String(reflecting: Element.self) | |
guard let scope = self.scopes[string] else { | |
fatalError("The object of type \(string) is not registered") | |
} | |
switch scope { | |
case .new: | |
let f = self.functions[string] as! (DIResolver) -> Element | |
return f(self) | |
case .singleton: | |
if let obj = singletons[string] as? Element { | |
return obj | |
} else { | |
let f = self.functions[string] as! (DIResolver) -> Element | |
let obj = f(self) | |
singletons[string] = obj | |
return obj | |
} | |
} | |
} | |
func resolve<Element, Param1>(type: Element.Type, param: Param1) -> Element { | |
let string = String(reflecting: Element.self) | |
guard let scope = self.scopes[string] else { | |
fatalError("The object of type \(string) is not registered") | |
} | |
switch scope { | |
case .new: | |
let f = self.functions[string] as! (DIResolver, Param1) -> Element | |
return f(self, param) | |
case .singleton: | |
if let obj = singletons[string] as? Element { | |
return obj | |
} else { | |
let f = self.functions[string] as! (DIResolver, Param1) -> Element | |
let obj = f(self, param) | |
singletons[string] = obj | |
return obj | |
} | |
} | |
} | |
func resolve<Element, Param1, Param2>(type: Element.Type, params: (Param1, Param2)) -> Element { | |
let string = String(reflecting: Element.self) | |
guard let scope = self.scopes[string] else { | |
fatalError("The object of type \(string) is not registered") | |
} | |
switch scope { | |
case .new: | |
let f = self.functions[string] as! (DIResolver, Param1, Param2) -> Element | |
return f(self, params.0, params.1) | |
case .singleton: | |
if let obj = singletons[string] as? Element { | |
return obj | |
} else { | |
let f = self.functions[string] as! (DIResolver, Param1, Param2) -> Element | |
let obj = f(self, params.0, params.1) | |
singletons[string] = obj | |
return obj | |
} | |
} | |
} | |
func resolve<Element, Param1, Param2, Param3>(type: Element.Type, params: (Param1, Param2, Param3)) -> Element { | |
let string = String(reflecting: Element.self) | |
guard let scope = self.scopes[string] else { | |
fatalError("The object of type \(string) is not registered") | |
} | |
switch scope { | |
case .new: | |
let f = self.functions[string] as! (DIResolver, Param1, Param2, Param3) -> Element | |
return f(self, params.0, params.1, params.2) | |
case .singleton: | |
if let obj = singletons[string] as? Element { | |
return obj | |
} else { | |
let f = self.functions[string] as! (DIResolver, Param1, Param2, Param3) -> Element | |
let obj = f(self, params.0, params.1, params.2) | |
singletons[string] = obj | |
return obj | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment