I completely fell in love with Dependency Injection. I enjoy the way it gives you the possibility to follow SOLID principles, the way it prevents Spaghetti Code. I used Dagger in one of my Android project and everything is more clean, modular and testable. Now I'm working on a Swift project. I would like to follow this kind of design pattern without using any third-party libraries (due to lacks of the current codebase and project commitments). So, I decided to create an homemade implementation.
import UIKit
class DependencyContainer {
private var dependencies = [String: AnyObject]()
struct Static {
static var instance: DependencyContainer?
}
static var shared: DependencyContainer {
if Static.instance == nil {
Static.instance = DependencyContainer()
}
return Static.instance!
}
init() {
AppDelegate.print("Dependency container instantiated")
}
func resolve(_ classIdentifier: String) -> AnyObject {
if dependencies[classIdentifier] == nil {
dependencies[classIdentifier] = getClassInstance(classIdentifier)
}
return dependencies[classIdentifier]!
}
private func getClassInstance(_ classIdentifier: String) -> AnyObject {
var instance: AnyObject! = nil
let classInstance = NSClassFromString(classIdentifier) as! NSObject.Type
instance = classInstance.init()
return instance
}
func dispose() {
DependencyContainer.Static.instance = nil
}
}
Where I need to inject a dependency I do it as follows:
dataRepository = DependencyContainer.shared.resolve(NSStringFromClass(DataRepositoryImplementation)) as! DataRepository
Everything is working fine at the moment but I think that there are lots of limitations with this kind of approach. Do you have any suggestions?
Yes, with your approach you'll need to register all your application objects to a single container. Also you're not using Generics to infer the type you're resolving and make your container Type-safe.
You can use https://github.com/JulianAlonso/Injection , it's type safe, have granularity, and its a very lightweight library.
I know an ultra-light dependency injection container. DIContainer
It's nice because you can resolve the dependencies using @Injected
before the properties, or if you prefer, you can call the method resolve
.
For example:
@Injected(.githubService)
var githubService: FetchService
@Injected(.by(type: FetchService.self, withKey: "gitlab"))
var gitlabService: FetchService
@InjectedSafe
var externalService: ExternalSingletonService?
or
let githubService = try? Container.standard.resolve(.githubService)
let gitlabService = try? Container.standard.resolve(.by(type: FetchService.self, withKey: "gitlab"))
let externalService = try? Container.standard.resolve(.by(type: ExternalSingletonService.self))
I hope it helps you with your achievement.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.