-
Notifications
You must be signed in to change notification settings - Fork 72
Auto injection
Auto-injection lets your resolve all property dependencies of the instance resolved by container with just one call, also allowing a simpler syntax to register circular dependencies.
protocol Server {
weak var client: Client? { get }
}
protocol Client: class {
var server: Server? { get }
}
class ServerImp: Server {
private let injectedClient = InjectedWeak<Client>()
var client: Client? { return injectedClient.value }
}
class ClientImp: Client {
private let injectedServer = Injected<Server>()
var server: Server? { get { return injectedServer.value} }
}
container.register(.Shared) { ServerImp() as Server }
container.register(.Shared) { ClientImp() as Client }
let client = try! container.resolve() as Client
Auto-Injected properties are required by default, so if container fails to resolve one of them it will fail to resolve the whole object graph. You can make it optional providing false
value for required
parameter in Injected
or InjectedWeak
constructor.
Auto-injection is performed before calling resolveDependencies
block of corresponding definition.
Tip: You can use either
Injected<T>
andInjectedWeak<T>
wrappers provided by Dip, or your own wrappers (even plainBox<T>
) that conform toAutoInjectedPropertyBox
protocol. This way you can minimise coupling with Dip.
If you try to resolve type that uses auto-injected properties with named definition the tag that you use to resolve will be implicitly used to resolve all the properties. That can lead to unexpected not shared dependencies in the graph.
class ServiceImp: Service {
let config = Injected<Config>()
let dataStore = Injected<DataStore>()
}
container.register() { ServiceImp() as Service }
container.register(tag: "dev") { DevConfig() as Config }
container.register(tag: "prod") { ProdConfig() as Config }
container.register(.singleton) { DataStore() }
let devService = try! container.resolve(tag: "dev") as Service
let prodService = try! container.resolve(tag: "prod") as Service
devService.config.value !== prodService.config.value //expected
devService.dataStore.value !== prodService.dataStore.value //not expected
To avoid that specify tag in injected property explicitly. You can use nil
to make container to not use any tag or some specific tag value.
class ServiceImp: Service {
let config = Injected<Config>()
let dataStore = Injected<DataStore>(tag: nil)
}
let devService = try! container.resolve(tag: "dev") as Service
let prodService = try! container.resolve(tag: "prod") as Service
devService.config.value !== prodService.config.value //still different instances as expected
devService.dataStore.value === prodService.dataStore.value //shared instance now