You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
3.8 KiB
130 lines
3.8 KiB
//
|
|
// 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
|
|
}
|