Last active
May 22, 2018 21:22
-
-
Save dneprDroid/f5f9c1f46cb0b83377d075df0c3cde8a to your computer and use it in GitHub Desktop.
Simple DI - Swift4
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
import Foundation | |
class A : DInjectEntity { } | |
class B : DInjectEntity { | |
var a:A! | |
} | |
class C : DInjectEntity { } | |
class Some { | |
lazy var a:A = self~ | |
lazy var a1:A = self~ | |
lazy var b:B = self~ | |
lazy var c:C = self~ | |
} | |
extension Some : DInject { | |
class func provide(container: DIContainer, this:Some) { | |
container << { _ in | |
return A() | |
} | |
container << { cont -> B in | |
let b = B() | |
b.a = cont.resolve(of: A.self) | |
return b | |
} | |
} | |
} | |
// Init-on | |
DIContainer.main << { _ in | |
return C() | |
} | |
let some = Some() | |
let a = some.a | |
let b = some.b | |
let c = some.c |
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
import Foundation | |
typealias DIResolver<T> = (_ container: DIContainer)->T | |
class DIContainer { | |
typealias EntityID = String | |
fileprivate(set) var dependencies:[EntityID : DIResolver<Any>] = [:] | |
fileprivate init(){} | |
static var main = DIContainer() | |
func resolve<T:DInjectEntity>(of type:T.Type)->T { | |
return resolve() | |
} | |
func resolve<T:DInjectEntity>()->T { | |
guard let dep = dependencies[T.__id] else { | |
fatalError("Dependency `\(T.self)` not registered") | |
} | |
return dep(self) as! T | |
} | |
} | |
protocol DInject { | |
static func provide(container:DIContainer, this:Self) | |
} | |
protocol DInjectEntity { } | |
extension DInjectEntity { | |
fileprivate static var __id:String { | |
return String.init(describing: Self.self) | |
} | |
} | |
private var _KEY_CONTAINER = "_KEY_CONTAINER" | |
postfix operator ~ | |
postfix func ~<T : DInject, R:DInjectEntity>(instance: T)->R { | |
let container:DIContainer = { | |
if let c = objc_getAssociatedObject(instance, &_KEY_CONTAINER) as? DIContainer { | |
return c | |
} | |
let c = DIContainer() | |
objc_setAssociatedObject(instance, &_KEY_CONTAINER, | |
c, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) | |
T.provide(container: c, this: instance) | |
return c | |
}() | |
let id = R.__id | |
guard let resolver = container.dependencies[id] | |
?? DIContainer.main.dependencies[id] else { | |
fatalError("Not registered type `\(R.self)` in `\(T.self)`") | |
} | |
return resolver(container) as! R | |
} | |
func << <R : DInjectEntity> (lhs: DIContainer, rhs: @escaping DIResolver<R>) { | |
let id = R.__id | |
lhs.dependencies[id] = rhs | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment