-
Notifications
You must be signed in to change notification settings - Fork 0
/
Container.swift
66 lines (57 loc) · 2.18 KB
/
Container.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import Foundation
class Container {
fileprivate static var registrations = [AnyHashable : () -> Any]()
fileprivate static var lock = NSRecursiveLock()
static func register<T>(_: T.Type, constructor: @escaping () -> Any) {
let dependencyName = String(describing: T.self)
registrations[dependencyName] = constructor
}
static func registerAsSingleton<T>(_: T.Type, constructor: @escaping () -> Any) {
let dependencyName = String(describing: T.self)
var instance: Any?
let resolver: () -> Any = {
if instance == nil {
instance = constructor()
return instance!
} else {
return instance!
}
}
registrations[dependencyName] = resolver
}
//Weak may only be applied to class and class-bound types, not 'Any'
static func registerWeakSingleton<T>(_: T.Type, constructor: @escaping () -> AnyObject) {
let dependencyName = String(describing: T.self)
var instance: AnyObject?
instance = nil
let resolver: () -> AnyObject = { [weak instance] in
if let instance = instance {
return instance
} else {
let newInstance = threadSafe(constructor())
instance = newInstance
return newInstance
}
}
registrations[dependencyName] = resolver
}
static func resolve<T>(type: T.Type = T.self) -> T {
let dependencyName = String(describing: T.self)
guard let resolver = registrations[dependencyName] else {
fatalError("No registration for type \(dependencyName)")
}
guard let result = resolver() as? T else {
fatalError("Can't cast registration to type \(dependencyName)")
}
return result
}
static func remove<T>(type: T.Type) {
let dependencyName = String(reflecting: T.self)
registrations.removeValue(forKey: dependencyName)
}
fileprivate static func threadSafe<T>(_ closure: @autoclosure ()->T) -> T {
lock.lock()
defer { lock.unlock() }
return closure()
}
}