Skip to content

Instantly share code, notes, and snippets.

@dneprDroid
Last active May 22, 2018 21:22
Show Gist options
  • Save dneprDroid/f5f9c1f46cb0b83377d075df0c3cde8a to your computer and use it in GitHub Desktop.
Save dneprDroid/f5f9c1f46cb0b83377d075df0c3cde8a to your computer and use it in GitHub Desktop.
Simple DI - Swift4
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
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