SwiftDependencyContainer
is a lightweight Dependency Container leveraging code generation to make setting up and managing dependencies easier than ever.
Objects registered as Singleton
are retained throughout the container's' lifetime, once resolved. Marked as eager will create the instance immediately, when the bootstrap
method is called. Objects registered as Factory
will return a new instance every time it's being resolved.
Required dependencies to instantiate an object using constructor injection can be auto-wired, assuming they are registered in the container.
Register one instance for multiple types, allowing for more flexible and maintainable code.
Manage dependencies using hashable keys, enabling registering different implementations for the same protocol or tpye.
For a magical setup experience thanks to code generation.
Examples contains a demonstration for each use case.
You can use the following annotiations for automatic dependency resolution:
/// @Singleton
/// @EagerSingleton
/// @Singleton(types: [])
/// @EagerSingleton(types: [])
/// @Factory
This is the entry point of your depdencies.
All it takes is an object that confirms to the AutoSetup
protocol.
import SwiftDependencyContainer
struct MyDependencies: AutoSetup {
let container = DependencyContainer()
}
After building your project, all necessary code for registering and resolving dependencies will be automatically generated and available.
To bootstrap your DependencyContainer
call the setup
method of your type implementing AutoSetup
.
MyDependencies.setup()
Note: You won't be able to register any more dependencies after setup
has been called.
At this point you are ready to go. No more code that needs to be written!
There are two ways to access your dependencies:
/// @Singleton
class MyType {}
Direct Access
All your dependencies have a resolve
method, which can be used to get the instance from the DependencyContainer
.
MyType.resolve() // generated
Composition Root Access
Every registered dependency is also available as static var
at your type implementing AutoSetup
.
MyDependencies.myType // generated
AutoSetup
is great and convinient, but some scenarios require more flexibility.
Manually register dependencies if needed by overrideing the optional override
method of the AutoSetup
protocol.
struct MyDependencies: AutoSetup {
let container = DependencyContainer()
func override(_ container: DependencyContainer) throws {
try container.register(Storage.self) { UserDefaults() } // register
}
static var storage: Storage { resolve() } // resolve
}
Note: Please feel free to open a ticket if you feel like the usage of your override
should be part of this framework!
Take a look at Examples for more details.
For those who prefer the traditional way:
let container = DependencyContainer()
try container.register { Singleton1() }
// resolve other co-dependencies
try container.register { Singleton2(other: try $0.resolve()) }
// register instance for another type
try container.register(Abstraction.self) { Singleton1() }
// register instance for several other types
try container.register([Abstraction1.self, Abstraction2.self]) { Singleton1() }
// register instance for a key
try container.register("MyKey") { Singleton1() }
All register
methods include an isEager: Bool
parameter. Eager dependencies are resolved upon container bootstrap.
Note: Keys are required to be Hashable
.
try container.bootstrap()
let singleton: Singleton1 = try container.resolve()
let singleton1: Singleton1 = try container.resolve("MyKey")
let singleton2: Abstraction2 = try container.resolve()
You can use the Swift Package Manager to install SwiftDependencyContainer
by adding it as a dependency to your Package.swift
file:
dependencies: [
.package(url: "[email protected]:davidscheutz/SwiftDependencyContainer.git", from: "0.2.0")
]
Make sure to add SwiftDependencyContainer
as a dependency to your Target.
Select your Project -> Your Target -> Build Phases -> Add CodeGeneratorPlugin (SwiftDependencyContainer)
The codegen runs now as part of the build phase, every time you compile your project.
Contributions to SwiftDependencyContainer
are welcomed and encouraged!
It is easy to get involved. Open an issue to discuss a new feature, write clean code, show some love using unit tests and open a Pull Request.
A list of contributors will be available through GitHub.
PS: Check the open issues and pull requests for existing discussions.
SwiftDependencyContainer
is available under the MIT license.
This project uses Sourcery for the code generation.