Last active
May 6, 2020 07:06
-
-
Save devxoul/d154cb35010a04faa293b4c958b2c79d to your computer and use it in GitHub Desktop.
Conceptual strong-typed DI container
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protocol ContainerProtocol { | |
associatedtype Service | |
associatedtype Nested: ContainerProtocol | |
var service: Service { get } | |
var nestedContainer: () -> Nested { get } | |
} | |
struct TypedContainer<Service, Nested: ContainerProtocol>: ContainerProtocol { | |
let service: Service | |
let nestedContainer: () -> Nested | |
init(_ type: Service.Type, service: Service, nestedContainer: @autoclosure @escaping () -> Nested) { | |
self.service = service | |
self.nestedContainer = nestedContainer | |
} | |
func register<T>(_ type: T.Type, service newService: T) -> TypedContainer<T, Self> { | |
return TypedContainer<T, Self>(T.self, service: newService, nestedContainer: self) | |
} | |
func resolve(_ type: Service.Type) -> Service { | |
return self.service | |
} | |
typealias Nested1 = Nested | |
typealias Nested2 = Nested1.Nested | |
typealias Nested3 = Nested2.Nested | |
typealias Nested4 = Nested3.Nested | |
typealias Nested5 = Nested4.Nested | |
private var nestedContainer1: () -> Nested1 { self.nestedContainer } | |
private var nestedContainer2: () -> Nested2 { self.nestedContainer1().nestedContainer } | |
private var nestedContainer3: () -> Nested3 { self.nestedContainer2().nestedContainer } | |
private var nestedContainer4: () -> Nested4 { self.nestedContainer3().nestedContainer } | |
private var nestedContainer5: () -> Nested5 { self.nestedContainer4().nestedContainer } | |
func resolve(_ type: Nested1.Service.Type) -> Nested1.Service { return self.nestedContainer1().service } | |
func resolve(_ type: Nested2.Service.Type) -> Nested2.Service { return self.nestedContainer2().service } | |
func resolve(_ type: Nested3.Service.Type) -> Nested3.Service { return self.nestedContainer3().service } | |
func resolve(_ type: Nested4.Service.Type) -> Nested4.Service { return self.nestedContainer4().service } | |
func resolve(_ type: Nested5.Service.Type) -> Nested5.Service { return self.nestedContainer5().service } | |
} | |
struct Container: ContainerProtocol { | |
let service: Void = Void() | |
let nestedContainer: () -> Container = { (nil as Container?)!} | |
func register<T>(_ type: T.Type, service newService: T) -> TypedContainer<T, Container> { | |
return TypedContainer<T, Container>(T.self, service: newService, nestedContainer: self.nestedContainer()) | |
} | |
func resolve(_ type: Service.Type) -> Service { | |
return (nil as Service?)! | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
protocol NetworkingProtocol {} | |
class Networking: NetworkingProtocol {} | |
protocol UserServiceProtocol {} | |
class UserService: UserServiceProtocol {} | |
protocol StyleServiceProtocol {} | |
class StyleService: StyleServiceProtocol {} | |
protocol UknownServiceProtocol {} | |
class UknownService: UknownServiceProtocol {} | |
let container = Container() | |
.register(NetworkingProtocol.self, service: Networking()) | |
.register(UserServiceProtocol.self, service: UserService()) | |
.register(StyleServiceProtocol.self, service: StyleService()) | |
print(container) | |
print(container.resolve(NetworkingProtocol.self)) | |
print(container.resolve(UserServiceProtocol.self)) | |
print(container.resolve(StyleServiceProtocol.self)) | |
print(container.resolve(UknownServiceProtocol.self)) // compile error |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment