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.
101 lines
3.7 KiB
101 lines
3.7 KiB
//
|
|
// Copyright © 2019 Swinject Contributors. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
// A generic-type-free protocol to be the type of values in a strongly-typed collection.
|
|
internal protocol ServiceEntryProtocol: AnyObject {
|
|
func describeWithKey(_ serviceKey: ServiceKey) -> String
|
|
var objectScope: ObjectScopeProtocol { get }
|
|
var storage: InstanceStorage { get }
|
|
var factory: FunctionType { get }
|
|
var initCompleted: (FunctionType)? { get }
|
|
var serviceType: Any.Type { get }
|
|
}
|
|
|
|
/// The `ServiceEntry<Service>` class represents an entry of a registered service type.
|
|
/// As a returned instance from a `register` method of a `Container`, some configurations can be added.
|
|
public final class ServiceEntry<Service>: ServiceEntryProtocol {
|
|
fileprivate var initCompletedActions: [(Resolver, Service) -> Void] = []
|
|
internal let serviceType: Any.Type
|
|
internal let argumentsType: Any.Type
|
|
|
|
internal let factory: FunctionType
|
|
internal weak var container: Container?
|
|
|
|
internal var objectScope: ObjectScopeProtocol = ObjectScope.graph
|
|
internal lazy var storage: InstanceStorage = { [unowned self] in
|
|
self.objectScope.makeStorage()
|
|
}()
|
|
|
|
internal var initCompleted: FunctionType? {
|
|
guard !initCompletedActions.isEmpty else { return nil }
|
|
|
|
return { [weak self] (resolver: Resolver, service: Any) -> Void in
|
|
guard let strongSelf = self else { return }
|
|
strongSelf.initCompletedActions.forEach { $0(resolver, service as! Service) }
|
|
}
|
|
}
|
|
|
|
internal init(serviceType: Service.Type, argumentsType: Any.Type, factory: FunctionType) {
|
|
self.serviceType = serviceType
|
|
self.argumentsType = argumentsType
|
|
self.factory = factory
|
|
}
|
|
|
|
internal convenience init(
|
|
serviceType: Service.Type,
|
|
argumentsType: Any.Type,
|
|
factory: FunctionType,
|
|
objectScope: ObjectScope
|
|
) {
|
|
self.init(serviceType: serviceType, argumentsType: argumentsType, factory: factory)
|
|
self.objectScope = objectScope
|
|
}
|
|
|
|
/// Specifies the object scope to resolve the service.
|
|
///
|
|
/// - Parameter scope: The `ObjectScopeProtocol` value.
|
|
///
|
|
/// - Returns: `self` to add another configuration fluently.
|
|
@discardableResult
|
|
public func inObjectScope(_ objectScope: ObjectScopeProtocol) -> Self {
|
|
self.objectScope = objectScope
|
|
return self
|
|
}
|
|
|
|
/// Specifies the object scope to resolve the service.
|
|
/// Performs the same functionality as `inObjectScope(_: ObjectScopeProtocol) -> Self`,
|
|
/// but provides more convenient usage syntax.
|
|
///
|
|
/// - Parameter scope: The `ObjectScope` value.
|
|
///
|
|
/// - Returns: `self` to add another configuration fluently.
|
|
@discardableResult
|
|
public func inObjectScope(_ objectScope: ObjectScope) -> Self {
|
|
return inObjectScope(objectScope as ObjectScopeProtocol)
|
|
}
|
|
|
|
/// Adds the callback to setup the instance after its `init` completes.
|
|
/// *Property or method injections* can be performed in the callback.
|
|
/// To resolve *circular dependencies*, `initCompleted` must be used.
|
|
///
|
|
/// - Parameter completed: The closure to be called after the instantiation of the registered service.
|
|
///
|
|
/// - Returns: `self` to add another configuration fluently.
|
|
@discardableResult
|
|
public func initCompleted(_ completed: @escaping (Resolver, Service) -> Void) -> Self {
|
|
initCompletedActions.append(completed)
|
|
return self
|
|
}
|
|
|
|
internal func describeWithKey(_ serviceKey: ServiceKey) -> String {
|
|
return description(
|
|
serviceType: serviceType,
|
|
serviceKey: serviceKey,
|
|
objectScope: objectScope,
|
|
initCompleted: initCompletedActions
|
|
)
|
|
}
|
|
}
|