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.
 
 
 
 

124 lines
5.0 KiB

//
// Copyright © 2019 Swinject Contributors. All rights reserved.
//
/// The `Assembler` provides a means to build a container via `Assembly` instances.
public final class Assembler {
/// the container that each assembly will build its `Service` definitions into
private let container: Container
/// expose the container as a resolver so `Service` registration only happens within an assembly
public var resolver: Resolver {
return container
}
/// Will create an empty `Assembler`
///
/// - parameter container: the baseline container
///
public init(container: Container? = Container()) {
self.container = container!
}
/// Will create an empty `Assembler`
///
/// - parameter parentAssembler: the baseline assembler
/// - parameter defaultObjectScope: default object scope for container
/// - parameter behaviors: list of behaviors to be added to the container
public init(parentAssembler: Assembler?, defaultObjectScope: ObjectScope = .graph, behaviors: [Behavior] = []) {
container = Container(
parent: parentAssembler?.container,
defaultObjectScope: defaultObjectScope,
behaviors: behaviors
)
}
/// Will create a new `Assembler` with the given `Assembly` instances to build a `Container`
///
/// - parameter assemblies: the list of assemblies to build the container from
/// - parameter container: the baseline container
///
@available(*, deprecated, message: "Use not throwing alternative: init(_:, container:)")
public convenience init(assemblies: [Assembly], container: Container? = Container()) throws {
if let container = container {
self.init(assemblies, container: container)
} else {
self.init(assemblies)
}
}
/// Will create a new `Assembler` with the given `Assembly` instances to build a `Container`
///
/// - parameter assemblies: the list of assemblies to build the container from
/// - parameter container: the baseline container
///
public init(_ assemblies: [Assembly], container: Container = Container()) {
self.container = container
run(assemblies: assemblies)
}
/// Will create a new `Assembler` with the given `Assembly` instances to build a `Container`
///
/// - parameter assemblies: the list of assemblies to build the container from
/// - parameter parentAssembler: the baseline assembler
///
@available(*, deprecated, message: "Use not throwing alternative: init(_:, parent:)")
public convenience init(assemblies: [Assembly], parentAssembler: Assembler?) throws {
self.init(_: assemblies, parent: parentAssembler)
}
/// Will create a new `Assembler` with the given `Assembly` instances to build a `Container`
///
/// - parameter assemblies: the list of assemblies to build the container from
/// - parameter parent: the baseline assembler
/// - parameter defaultObjectScope: default object scope for container
/// - parameter behaviors: list of behaviors to be added to the container
public init(
_ assemblies: [Assembly],
parent: Assembler?,
defaultObjectScope: ObjectScope = .graph,
behaviors: [Behavior] = []
) {
container = Container(parent: parent?.container, defaultObjectScope: defaultObjectScope, behaviors: behaviors)
run(assemblies: assemblies)
}
/// Will apply the assembly to the container. This is useful if you want to lazy load an assembly into the
/// assembler's container.
///
/// If this assembly type is load aware, the loaded hook will be invoked right after the container has assembled
/// since after each call to `addAssembly` the container is fully loaded in its current state. If you wish to
/// lazy load several assemblies that have interdependencies between each other use `appyAssemblies`
///
/// - parameter assembly: the assembly to apply to the container
///
public func apply(assembly: Assembly) {
run(assemblies: [assembly])
}
/// Will apply the assemblies to the container. This is useful if you want to lazy load several assemblies into the
/// assembler's container
///
/// If this assembly type is load aware, the loaded hook will be invoked right after the container has assembled
/// since after each call to `addAssembly` the container is fully loaded in its current state.
///
/// - parameter assemblies: the assemblies to apply to the container
///
public func apply(assemblies: [Assembly]) {
run(assemblies: assemblies)
}
// MARK: Private
private func run(assemblies: [Assembly]) {
// build the container from each assembly
for assembly in assemblies {
assembly.assemble(container: container)
}
// inform all of the assemblies that the container is loaded
for assembly in assemblies {
assembly.loaded(resolver: resolver)
}
}
}