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

//
// 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
)
}
}