diff --git a/README.md b/README.md index e391803..dc02666 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,21 @@ Define injected properties: @Injected var storage: StorageService ``` +Iterate over all dependencies: + +```swift +for service in dependencies { + service.start() +} +``` + +Access using dynamic member lookup: + +```swift +let location: LocationProtocol? = dependencies.locationService // Erase type to protocol +let storage: StorageService = dependencies.storageService! // Force unwarp if needed +``` + More details on implementation and usage is [here](https://grigory.nl/posts/swift-property-wrappers/) ### How to add it to Xcode project? diff --git a/Sources/Injected/Injected.swift b/Sources/Injected/Injected.swift index 49c0aa6..fbef9e2 100644 --- a/Sources/Injected/Injected.swift +++ b/Sources/Injected/Injected.swift @@ -6,6 +6,8 @@ // Copyright © 2020 Grigory Avdyushin. All rights reserved. // +import Foundation + public struct Dependency { public typealias ResolveBlock = () -> T @@ -24,6 +26,7 @@ public struct Dependency { } } +@dynamicMemberLookup open class Dependencies: Sequence { static private(set) var shared = Dependencies() @@ -43,6 +46,7 @@ open class Dependencies: Sequence { register(dependency()) } + /// Builds (resolves) all dependencies graph open func build() { // We assuming that at this point all needed dependencies are registered for index in dependencies.startIndex.. AnyIterator { var iter = dependencies.makeIterator() return AnyIterator { iter.next()?.value } } + /// Return dependency by given camelCase name of the object type + /// For example: if dependency registered as `MyService` name should be `myService` + public subscript(dynamicMember name: String) -> T? { + dependencies.first { $0.name == name.prefix(1).capitalized + name.dropFirst() }?.value as? T + } + // MARK: - Private fileprivate init() { } diff --git a/Tests/InjectedTests/InjectedTests.swift b/Tests/InjectedTests/InjectedTests.swift index cc848f5..ce8f2b3 100644 --- a/Tests/InjectedTests/InjectedTests.swift +++ b/Tests/InjectedTests/InjectedTests.swift @@ -40,6 +40,19 @@ final class InjectedTests: XCTestCase { XCTAssertEqual(serviceB.fetch().first, "Foo") } + func testIterator() { + for service in deps { + XCTAssertTrue(service is ServiceA || service is ServiceB) + } + } + + func testMemberLookup() { + let serviceA: ServiceA = deps.serviceAImpl! + XCTAssertTrue(serviceA.run()) + let serviceB: ServiceB = deps.serviceBImpl! + XCTAssertEqual(serviceB.fetch().first, "Foo") + } + static var allTests = [ ("testExample", testExample), ]