-
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 ClientAuto-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 toAutoInjectedPropertyBoxprotocol. 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 expectedTo 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