-
Notifications
You must be signed in to change notification settings - Fork 3
Container
Dependency Injection (DI) containers or Inversion of Control (IoC) containers allow to make an object graph, automate objects composition and manage their lifecycle.
Saber uses the term "service" for "object".
There're no limitations on how many containers and their services you want to declare.
To define a new container add a protocol
and annotate it:
// @saber.container(AppContainer)
// @saber.scope(App)
protocol AppContaining {
}
After running Saber you get a AppContainer.saber.swift
file with a class named AppContainer
, which conforms to AppContaining
:
// NOTE: `internal` is used by default and can be changed via Saber configuration
internal class AppContainer: AppContaining {
internal init() {
}
}
To add a simple service just declare a class
/struct
and set its scope:
// @saber.scope(App)
class Foo {
}
Run Saber and see how the container file has changed:
internal class AppContainer: AppContaining {
internal init() {
}
// NOTE: that's the same `internal`
internal var foo: Foo {
let foo = self.makeFoo()
return foo
}
// NOTE: a factory is always private for every service
private func makeFoo() -> Foo {
return Foo()
}
}
Now AppContainer
manages Foo
:
-
Foo
can be retrieved outside the container via thefoo
property -
Foo
can be used to resolve dependencies
Let's add another service named Bar
and set Foo
as its dependency:
// @saber.scope(App)
class Bar {
// @saber.inject
init(foo: Foo) {
// ...
}
}
Generated:
internal class AppContainer: AppContaining {
internal init() {
}
internal var foo: Foo {
let foo = self.makeFoo()
return foo
}
internal var bar: Bar {
let bar = self.makeBar()
return bar
}
private func makeFoo() -> Foo {
return Foo()
}
private func makeBar() -> Bar {
return Bar(foo: self.foo) // injected!
}
}
Now AppContainer
manages Bar
too and solves its dependency.
Saber supports not only initializer, but also property and method (or setter) injections.
All container annotations:
-
@saber.container(Name)
: name of a generated container class (e.g.@saber.container(AppContainer)
) and its filename:%Name%.saber.swift
(e.g.AppContainer.saber.swift
). -
@saber.scope(ScopeName)
: name of a container scope (e.g.@saber.scope(App)
). Every service is attached to a container via the same annotation. -
@saber.threadSafe
: [optional] makes a container thread-safe. -
@saber.dependsOn(OneContainer, AnotherContainer, ...)
: [optional] organizes a multiple inheritance, comma-separated list of containers to be inherited from. -
@saber.externals(A, B, ...)
: [optional] comma-separated list of container externals (e.g.@saber.externals(Env, Analytics)
). -
@saber.imports(A, B)
: [optional] comma-separated list of additional modules to import inside a generated container file (e.g.@saber.imports(UIKit, Alamofire)
).Foundation
is added by default.
- User's Guide
- Advanced