-
Notifications
You must be signed in to change notification settings - Fork 547
Expand file tree
/
Copy pathInstanceStorage.swift
More file actions
130 lines (106 loc) · 3.82 KB
/
InstanceStorage.swift
File metadata and controls
130 lines (106 loc) · 3.82 KB
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//
// Copyright © 2019 Swinject Contributors. All rights reserved.
//
/// Storage provided by `ObjectScope`. It is used by `Container` to persist resolved instances.
public protocol InstanceStorage: AnyObject {
var instance: Any? { get set }
func graphResolutionCompleted()
func instance(inGraph graph: GraphIdentifier) -> Any?
func setInstance(_ instance: Any?, inGraph graph: GraphIdentifier)
}
extension InstanceStorage {
public func graphResolutionCompleted() {}
public func instance(inGraph _: GraphIdentifier) -> Any? { return instance }
public func setInstance(_ instance: Any?, inGraph _: GraphIdentifier) { self.instance = instance }
}
/// Persists storage during the resolution of the object graph
public final class GraphStorage: InstanceStorage {
private var instances = [GraphIdentifier: Weak<Any>]()
public var instance: Any?
public init() {}
public func graphResolutionCompleted() {
instance = nil
}
public func instance(inGraph graph: GraphIdentifier) -> Any? {
return instances[graph]?.value
}
public func setInstance(_ instance: Any?, inGraph graph: GraphIdentifier) {
self.instance = instance
if instances[graph] == nil { instances[graph] = Weak() }
instances[graph]?.value = instance
}
}
/// Persists stored instance until it is explicitly discarded.
public final class PermanentStorage: InstanceStorage {
public var instance: Any?
public init() {}
}
/// Does not persist stored instance.
public final class TransientStorage: InstanceStorage {
public var instance: Any? {
get { return nil }
set {} // swiftlint:disable:this unused_setter_value
}
public init() {}
}
/// Does not persist value types.
/// Persists reference types as long as there are strong references to given instance.
public final class WeakStorage: InstanceStorage {
private var _instance = Weak<Any>()
public var instance: Any? {
get { return _instance.value }
set { _instance.value = newValue }
}
public init() {}
}
/// Combines the behavior of multiple instance storages.
/// Instance is persisted as long as at least one of the underlying storages is persisting it.
public final class CompositeStorage: InstanceStorage {
private let components: [InstanceStorage]
public var instance: Any? {
get {
#if swift(>=4.1)
return components.compactMap { $0.instance }.first
#else
return components.flatMap { $0.instance }.first
#endif
}
set { components.forEach { $0.instance = newValue } }
}
public init(_ components: [InstanceStorage]) {
self.components = components
}
public func graphResolutionCompleted() {
components.forEach { $0.graphResolutionCompleted() }
}
public func setInstance(_ instance: Any?, inGraph graph: GraphIdentifier) {
components.forEach { $0.setInstance(instance, inGraph: graph) }
}
public func instance(inGraph graph: GraphIdentifier) -> Any? {
#if swift(>=4.1)
return components.compactMap { $0.instance(inGraph: graph) }.first
#else
return components.flatMap { $0.instance(inGraph: graph) }.first
#endif
}
}
private class Weak<Wrapped> {
private weak var object: AnyObject?
#if os(Linux)
var value: Wrapped? {
get {
guard let object = object else { return nil }
return object as? Wrapped
}
set { object = newValue.flatMap { $0 as? AnyObject } }
}
#else
var value: Wrapped? {
get {
guard let object = object else { return nil }
return object as? Wrapped
}
set { object = newValue as AnyObject? }
}
#endif
}