0001 // 0002 // Container.swift 0003 // Swinject 0004 // 0005 // Created by Yoichi Tagaya on 7/23/15. 0006 // Copyright © 2015 Swinject Contributors. All rights reserved. 0007 // 0008 0009 import Foundation 0010 0011 0012 /// represents the type that allows definition resolution and property retrieval 0013 public typealias ResolverType= protocol<Resolvable, PropertyRetrievable> 0014 0015 /// The `Container` class represents a dependency injection container, which stores registrations of services 0016 /// and retrieves registered services with dependencies injected. 0017 /// 0018 /// **Example to register:** 0019 /// 0020 /// let container = Container() 0021 /// container.register(A.self) { _ in B() } 0022 /// container.register(X.self) { r in Y(a: r.resolve(A.self)!) } 0023 /// 0024 /// **Example to retrieve:** 0025 /// 0026 /// let x = container.resolve(X.self)! 0027 /// 0028 /// where `A` and `X` are protocols, `B` is a type conforming `A`, and `Y` is a type conforming `X` and depending on `A`. 0029 public final class Container
Assembler.swift:17 public var resolver: ResolverType {AssemblyType.swift:26 func loaded(resolver: ResolverType)AssemblyType.swift:30 func loaded(resolver: ResolverType) {Container.Arguments.swift:37 factory: (ResolverType, Arg1) -> Service) -> ServiceEntry<Service>Container.Arguments.swift:57 factory: (ResolverType, Arg1, Arg2) -> Service) -> ServiceEntry<Service>Container.Arguments.swift:77 factory: (ResolverType, Arg1, Arg2, Arg3) -> Service) -> ServiceEntry<Service>Container.Arguments.swift:97 factory: (ResolverType, Arg1, Arg2, Arg3, Arg4) -> Service) -> ServiceEntry<Service>Container.Arguments.swift:117 factory: (ResolverType, Arg1, Arg2, Arg3, Arg4, Arg5) -> Service) -> ServiceEntry<Service>Container.Arguments.swift:137 factory: (ResolverType, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) -> Service) -> ServiceEntry<Service>Container.Arguments.swift:157 factory: (ResolverType, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) -> Service) -> ServiceEntry<Service>Container.Arguments.swift:177 factory: (ResolverType, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8) -> Service) -> ServiceEntry<Service>Container.Arguments.swift:197 factory: (ResolverType, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9) -> Service) -> ServiceEntry<Service>Container.Arguments.swift:235 typealias FactoryType = (ResolverType, Arg1) -> ServiceContainer.Arguments.swift:268 typealias FactoryType = (ResolverType, Arg1, Arg2) -> ServiceContainer.Arguments.swift:301 typealias FactoryType = (ResolverType, Arg1, Arg2, Arg3) -> ServiceContainer.Arguments.swift:334 typealias FactoryType = (ResolverType, Arg1, Arg2, Arg3, Arg4) -> ServiceContainer.Arguments.swift:367 typealias FactoryType = (ResolverType, Arg1, Arg2, Arg3, Arg4, Arg5) -> ServiceContainer.Arguments.swift:400 typealias FactoryType = (ResolverType, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) -> ServiceContainer.Arguments.swift:433 typealias FactoryType = (ResolverType, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) -> ServiceContainer.Arguments.swift:466 typealias FactoryType = (ResolverType, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8) -> ServiceContainer.Arguments.swift:499 typealias FactoryType = (ResolverType, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9) -> ServiceContainer.swift:74 factory: ResolverType -> Service) -> ServiceEntry<Service>Container.swift:137 typealias FactoryType = ResolverType -> ServiceContainer.swift:201 if let completed = entry.initCompleted as? (ResolverType, Service) -> () {ServiceEntry.swift:53 public func initCompleted(completed: (ResolverType, Service) -> ()) -> Self {{ 0030 private var services
Assembler.swift:14 private let container: ContainerAssembler.swift:25 public init(container: Container? = Container()) {Assembler.swift:25 public init(container: Container? = Container()) {Assembler.swift:34 container = Container(parent: parentAssembler?.container)Assembler.swift:43 public init(assemblies: [AssemblyType], propertyLoaders: [PropertyLoaderType]? = nil, container: Container? = Container()) throws {Assembler.swift:43 public init(assemblies: [AssemblyType], propertyLoaders: [PropertyLoaderType]? = nil, container: Container? = Container()) throws {Assembler.swift:60 container = Container(parent: parentAssembler?.container)AssemblyType.swift:19 func assemble(container: Container)Container.Arguments.swift:21 extension Container {Container.Arguments.swift:205 extension Container {Container.swift:31 private let parent: Container?Container.swift:39 public init(parent: Container? = nil) {Container.swift:49 public convenience init(parent: Container? = nil, @noescape registeringClosure: Container -> Void) {Container.swift:49 public convenience init(parent: Container? = nil, @noescape registeringClosure: Container -> Void) {Container.swift:112 extension Container: Resolvable {Container.swift:209 extension Container: PropertyRetrievable {SynchronizedResolver.swift:10 internal let container: ContainerSynchronizedResolver.swift:12 internal init(container: Container) {= [ServiceKey: ServiceEntryType]() 0031 private let parent
Container.swift:56 services.removeAll()Container.swift:82 services[key] = entryContainer.swift:155 services[key] = ownEntryContainer.swift:176 var entry = services[key] as? ServiceEntry<Service>: Container? 0032 private var resolutionPool
Container.swift:40 self.parent = parentContainer.swift:177 if entry == nil, let parent = self.parent {= ResolutionPool() 0033 private var properties
Container.swift:142 resolutionPool.incrementDepth()Container.swift:143 defer { resolutionPool.decrementDepth() }Container.swift:188 if usesPool, let pooledInstance = resolutionPool[key] as? Service {Container.swift:194 if let pooledInstance = resolutionPool[key] as? Service {Container.swift:198 resolutionPool[key] = resolvedInstance as Any= [String:AnyObject]() 0034 internal let lock
Container.swift:106 properties[key] = valueContainer.swift:221 return properties[name] as? Property: SpinLock // Used by SynchronizedResolver. 0035 0036 /// Instantiates a `Container` with its parent `Container`. The parent is optional. 0037 /// 0038 /// - Parameter parent: The optional parent `Container`. 0039 public init
Container.swift:41 self.lock = parent.map { $0.lock } ?? SpinLock()Container.swift:41 self.lock = parent.map { $0.lock } ?? SpinLock()SynchronizedResolver.Arguments.swift:24 return container.lock.sync {SynchronizedResolver.Arguments.swift:34 return container.lock.sync {SynchronizedResolver.Arguments.swift:43 return container.lock.sync {SynchronizedResolver.Arguments.swift:53 return container.lock.sync {SynchronizedResolver.Arguments.swift:62 return container.lock.sync {SynchronizedResolver.Arguments.swift:72 return container.lock.sync {SynchronizedResolver.Arguments.swift:81 return container.lock.sync {SynchronizedResolver.Arguments.swift:91 return container.lock.sync {SynchronizedResolver.Arguments.swift:100 return container.lock.sync {SynchronizedResolver.Arguments.swift:110 return container.lock.sync {SynchronizedResolver.Arguments.swift:119 return container.lock.sync {SynchronizedResolver.Arguments.swift:129 return container.lock.sync {SynchronizedResolver.Arguments.swift:138 return container.lock.sync {SynchronizedResolver.Arguments.swift:148 return container.lock.sync {SynchronizedResolver.Arguments.swift:157 return container.lock.sync {SynchronizedResolver.Arguments.swift:167 return container.lock.sync {SynchronizedResolver.Arguments.swift:176 return container.lock.sync {SynchronizedResolver.Arguments.swift:186 return container.lock.sync {SynchronizedResolver.swift:19 return container.lock.sync {SynchronizedResolver.swift:25 return container.lock.sync {(parent: Container? = nil) { 0040 self.parent = parent 0041 self.lock = parent.map { $0.lock } ?? SpinLock() 0042 } 0043 0044 /// Instantiates a `Container` with its parent `Container` and a closure registering services. The parent is optional. 0045 /// 0046 /// - Parameters: 0047 /// - parent: The optional parent `Container`. 0048 /// - registeringClosure: The closure registering services to the new container instance. 0049 public convenience init(parent: Container? = nil, @noescape registeringClosure: Container -> Void) { 0050 self.init(parent: parent) 0051 registeringClosure(self) 0052 } 0053 0054 /// Removes all registrations in the container. 0055 public func removeAll() { 0056 services.removeAll() 0057 } 0058 0059 /// Adds a registration for the specified service with the factory closure to specify how the service is resolved with dependencies. 0060 /// 0061 /// - Parameters: 0062 /// - serviceType: The service type to register. 0063 /// - name: A registration name, which is used to differenciate from other registrations 0064 /// that have the same service and factory types. 0065 /// - factory: The closure to specify how the service type is resolved with the dependencies of the type. 0066 /// It is invoked when the `Container` needs to instantiate the instance. 0067 /// It takes a `ResolverType` to inject dependencies to the instance, 0068 /// and returns the instance of the component type for the service. 0069 /// 0070 /// - Returns: A registered `ServiceEntry` to configure more settings with method chaining. 0071 public func register<Service>( 0072 serviceType: Service.Type, 0073 name: String? = nil, 0074 factory: ResolverType -> Service) -> ServiceEntry<Service> 0075 { 0076 return registerImpl(serviceType, factory: factory, name: name) 0077 } 0078 0079 internal func registerImpl
Assembler.swift:25 public init(container: Container? = Container()) {Assembler.swift:34 container = Container(parent: parentAssembler?.container)Assembler.swift:43 public init(assemblies: [AssemblyType], propertyLoaders: [PropertyLoaderType]? = nil, container: Container? = Container()) throws {Assembler.swift:60 container = Container(parent: parentAssembler?.container)Container.swift:50 self.init(parent: parent)<Service, Factory>(serviceType: Service.Type, factory: Factory, name: String?) -> ServiceEntry<Service> { 0080 let key = ServiceKey(factoryType: factory.dynamicType, name: name) 0081 let entry = ServiceEntry(serviceType: serviceType, factory: factory) 0082 services[key] = entry 0083 return entry 0084 } 0085 0086 /// Returns a synchronized view of the container for thread safety. 0087 /// The returned container is `Resolvable` type. Call this method after you finish all service registrations to the original container. 0088 /// 0089 /// - Returns: A synchronized container as `Resolvable`. 0090 public func synchronize() -> Resolvable { 0091 return SynchronizedResolver(container: self) 0092 } 0093 0094 /// 0095 /// Will apply the property loaded to the container. The loader will be invoked and the properties will be merged 0096 /// with the existing properties owned by this container. The order in which loaders are applied matters as you can 0097 /// apply multi property loaders to a single container so properties loaded from each loader will be merged. Therefore 0098 /// if loader A contains property "test.key" and loader B contains property "test.key" then if A is loaded, then B 0099 /// is loaded the value for "test.key" will come from loader B. 0100 /// 0101 /// - parameter loader: the loader to load properties into the container 0102 /// 0103 public func applyPropertyLoader
Container.Arguments.swift:39 return registerImpl(serviceType, factory: factory, name: name)Container.Arguments.swift:59 return registerImpl(serviceType, factory: factory, name: name)Container.Arguments.swift:79 return registerImpl(serviceType, factory: factory, name: name)Container.Arguments.swift:99 return registerImpl(serviceType, factory: factory, name: name)Container.Arguments.swift:119 return registerImpl(serviceType, factory: factory, name: name)Container.Arguments.swift:139 return registerImpl(serviceType, factory: factory, name: name)Container.Arguments.swift:159 return registerImpl(serviceType, factory: factory, name: name)Container.Arguments.swift:179 return registerImpl(serviceType, factory: factory, name: name)Container.Arguments.swift:199 return registerImpl(serviceType, factory: factory, name: name)Container.swift:76 return registerImpl(serviceType, factory: factory, name: name)(loader: PropertyLoaderType) throws { 0104 let props = try loader.load() 0105 for (key, value) in props { 0106 properties[key] = value 0107 } 0108 } 0109 } 0110 0111 // MARK: - Resolvable 0112 extension Container: Resolvable { 0113 /// Retrieves the instance with the specified service type. 0114 /// 0115 /// - Parameter serviceType: The service type to resolve. 0116 /// 0117 /// - Returns: The resolved service type instance, or nil if no registration for the service type is found in the `Container`. 0118 public func resolve
Assembler.swift:47 try self.container.applyPropertyLoader(propertyLoader)Assembler.swift:63 try self.container.applyPropertyLoader(propertyLoader)Assembler.swift:102 try self.container.applyPropertyLoader(propertyLoader)<Service>( 0119 serviceType: Service.Type) -> Service? 0120 { 0121 return resolve(serviceType, name: nil) 0122 } 0123 0124 0125 0126 /// Retrieves the instance with the specified service type and registration name. 0127 /// 0128 /// - Parameters: 0129 /// - serviceType: The service type to resolve. 0130 /// - name: The registration name. 0131 /// 0132 /// - Returns: The resolved service type instance, or nil if no registration for the service type and name is found in the `Container`. 0133 public func resolve
SynchronizedResolver.swift:20 return self.container.resolve(serviceType)<Service>( 0134 serviceType: Service.Type, 0135 name: String?) -> Service? 0136 { 0137 typealias FactoryType = ResolverType -> Service 0138 return resolveImpl(name) { (factory: FactoryType) in factory(self) } 0139 } 0140 0141 internal func resolveImpl
Container.swift:121 return resolve(serviceType, name: nil)SynchronizedResolver.swift:26 return self.container.resolve(serviceType, name: name)<Service, Factory>(name: String?, invoker: Factory -> Service) -> Service? { 0142 resolutionPool.incrementDepth() 0143 defer { resolutionPool.decrementDepth() } 0144 0145 var resolvedInstance: Service? 0146 let key = ServiceKey(factoryType: Factory.self, name: name) 0147 if let (entry, fromParent) = getEntry(key) as (ServiceEntry<Service>, Bool)? { 0148 switch entry.objectScope { 0149 case .None, .Graph: 0150 resolvedInstance = resolveEntry(entry, key: key, invoker: invoker) 0151 case .Container: 0152 let ownEntry: ServiceEntry<Service> 0153 if fromParent { 0154 ownEntry = entry.copyExceptInstance() 0155 services[key] = ownEntry 0156 } else { 0157 ownEntry = entry 0158 } 0159 0160 if ownEntry.instance == nil { 0161 ownEntry.instance = resolveEntry(entry, key: key, invoker: invoker) as Any 0162 } 0163 resolvedInstance = ownEntry.instance as? Service 0164 case .Hierarchy: 0165 if entry.instance == nil { 0166 entry.instance = resolveEntry(entry, key: key, invoker: invoker) as Any 0167 } 0168 resolvedInstance = entry.instance as? Service 0169 } 0170 } 0171 return resolvedInstance 0172 } 0173 0174 private func getEntry
Container.Arguments.swift:236 return resolveImpl(name) { (factory: FactoryType) in factory(self, argument) }Container.Arguments.swift:269 return resolveImpl(name) { (factory: FactoryType) in factory(self, arguments.0, arguments.1) }Container.Arguments.swift:302 return resolveImpl(name) { (factory: FactoryType) in factory(self, arguments.0, arguments.1, arguments.2) }Container.Arguments.swift:335 return resolveImpl(name) { (factory: FactoryType) in factory(self, arguments.0, arguments.1, arguments.2, arguments.3) }Container.Arguments.swift:368 return resolveImpl(name) { (factory: FactoryType) in factory(self, arguments.0, arguments.1, arguments.2, arguments.3, arguments.4) }Container.Arguments.swift:401 return resolveImpl(name) { (factory: FactoryType) in factory(self, arguments.0, arguments.1, arguments.2, arguments.3, arguments.4, arguments.5) }Container.Arguments.swift:434 return resolveImpl(name) { (factory: FactoryType) in factory(self, arguments.0, arguments.1, arguments.2, arguments.3, arguments.4, arguments.5, arguments.6) }Container.Arguments.swift:467 return resolveImpl(name) { (factory: FactoryType) in factory(self, arguments.0, arguments.1, arguments.2, arguments.3, arguments.4, arguments.5, arguments.6, arguments.7) }Container.Arguments.swift:500 return resolveImpl(name) { (factory: FactoryType) in factory(self, arguments.0, arguments.1, arguments.2, arguments.3, arguments.4, arguments.5, arguments.6, arguments.7, arguments.8) }Container.swift:138 return resolveImpl(name) { (factory: FactoryType) in factory(self) }<Service>(key: ServiceKey) -> (ServiceEntry<Service>, Bool)? { 0175 var fromParent = false 0176 var entry = services[key] as? ServiceEntry<Service> 0177 if entry == nil, let parent = self.parent { 0178 if let (parentEntry, _) = parent.getEntry(key) as (ServiceEntry<Service>, Bool)? { 0179 entry = parentEntry 0180 fromParent = true 0181 } 0182 } 0183 return entry.map { ($0, fromParent) } 0184 } 0185 0186 private func resolveEntry
Container.swift:147 if let (entry, fromParent) = getEntry(key) as (ServiceEntry<Service>, Bool)? {Container.swift:178 if let (parentEntry, _) = parent.getEntry(key) as (ServiceEntry<Service>, Bool)? {<Service, Factory>(entry: ServiceEntry<Service>, key: ServiceKey, invoker: Factory -> Service) -> Service { 0187 let usesPool = entry.objectScope != .None 0188 if usesPool, let pooledInstance = resolutionPool[key] as? Service { 0189 return pooledInstance 0190 } 0191 0192 let resolvedInstance = invoker(entry.factory as! Factory) 0193 if usesPool { 0194 if let pooledInstance = resolutionPool[key] as? Service { 0195 // An instance for the key might be added by the factory invocation. 0196 return pooledInstance 0197 } 0198 resolutionPool[key] = resolvedInstance as Any 0199 } 0200 0201 if let completed = entry.initCompleted as? (ResolverType, Service) -> () { 0202 completed(self, resolvedInstance) 0203 } 0204 return resolvedInstance 0205 } 0206 } 0207 0208 // MARK: - PropertyRetrievable 0209 extension Container: PropertyRetrievable { 0210 0211 /// Retrieves a property for the given name where the receiving property is optional. This is a limitation of 0212 /// how you can reflect a Optional<Foo> class type where you cannot determine the inner type is Foo without parsing 0213 /// the string description (yuck). So in order to inject into an optioanl property, you need to specify the type 0214 /// so we can properly cast the object 0215 /// 0216 /// - Parameter key: The name for the property 0217 /// - Parameter type: The type of the property 0218 /// 0219 /// - Returns: The value for the property name 0220 public func property<Property>(name: String) -> Property? { 0221 return properties[name] as? Property 0222 } 0223 } 0224
Container.swift:150 resolvedInstance = resolveEntry(entry, key: key, invoker: invoker)Container.swift:161 ownEntry.instance = resolveEntry(entry, key: key, invoker: invoker) as AnyContainer.swift:166 entry.instance = resolveEntry(entry, key: key, invoker: invoker) as Any