diff --git a/Sources/Grove/Grove.swift b/Sources/Grove/Grove.swift index 0e20713..046d500 100644 --- a/Sources/Grove/Grove.swift +++ b/Sources/Grove/Grove.swift @@ -19,7 +19,7 @@ public final class Grove: @unchecked Sendable { } private enum DependencyItem { - case initializer(() -> AnyObject, scope: Scope) + case initializer(() -> Any, scope: Scope) case instance(Any) } private var dependencyItemsMap = [String: DependencyItem]() @@ -34,11 +34,11 @@ public final class Grove: @unchecked Sendable { /// Registers a dependency's initializer /// - Parameters: - /// - initializer: Initializer for the dependency to be registered (ex. JSONEncoder.init, or { JSONEncoder() }) /// - type: Optional type of to use for registration (ex. JSONEncodingProtocol for the above initializer) /// - scope: Optional scope to use for registration: singleton or transient. Transient dependencies are initialized every time they are resolved + /// - initializer: Initializer for the dependency to be registered (ex. JSONEncoder.init, or { JSONEncoder() }) /// - public func register(_ initializer: @escaping () -> AnyObject, type: T.Type = T.self, scope: Scope = .singleton) { + public func register(as type: T.Type = T.self, scope: Scope = .singleton, _ initializer: @escaping () -> T) { Self.defaultContainerLock.lock() Self.defaultContainer = self Self.defaultContainerLock.unlock() @@ -50,10 +50,10 @@ public final class Grove: @unchecked Sendable { /// Registers using a value /// - Parameters: - /// - value: Value for the dependency to be registered /// - type: Optional type of to use for registration + /// - value: Value for the dependency to be registered /// - public func register(value: T, type: T.Type = T.self) { + public func register(as type: T.Type = T.self, value: T) { Self.defaultContainerLock.lock() Self.defaultContainer = self Self.defaultContainerLock.unlock() @@ -112,7 +112,7 @@ public final class Grove: @unchecked Sendable { } } - public func register(_ initializer: @escaping () -> T, scope: Scope = .singleton) where T: AnyObject { - register(initializer, type: T.self, scope: scope) + public func register(_ initializer: @escaping () -> T, scope: Scope = .singleton) { + register(as: T.self, scope: scope, initializer) } } diff --git a/Sources/Grove/PropertyWrapper.swift b/Sources/Grove/PropertyWrapper.swift index 8dab4a6..74cd695 100644 --- a/Sources/Grove/PropertyWrapper.swift +++ b/Sources/Grove/PropertyWrapper.swift @@ -9,9 +9,9 @@ import Foundation /// Grove resolution property wrapper /// -/// In most cases, where only a single container is used, this property wrapper can be used to simplify resolution. +/// This property wrapper can be used to simplify resolution. Optionally a container other than the default can be specified. /// -/// Allows to resolve dependencies in this fashion: +/// It allows to resolve dependencies in this fashion: /// ``` /// @Resolve var jsonEncoder: JSONEncodingProtocol /// ``` @@ -24,7 +24,7 @@ import Foundation public struct Resolve { public var wrappedValue: T - public init() { - self.wrappedValue = Grove.defaultContainer.resolve() + public init(container: Grove = .defaultContainer) { + self.wrappedValue = container.resolve() } } diff --git a/Tests/GroveTests/GroveTests.swift b/Tests/GroveTests/GroveTests.swift index 7bc7258..7d3f82c 100644 --- a/Tests/GroveTests/GroveTests.swift +++ b/Tests/GroveTests/GroveTests.swift @@ -8,6 +8,7 @@ private protocol TestProtocol { private final class TestClass: TestProtocol { var value: Int = 0 + func increment() { value += 1 } @@ -24,12 +25,13 @@ final class GroveTests: XCTestCase { Grove.defaultContainer.register(NotProtocolConformingTestClass.init) let testClass: NotProtocolConformingTestClass = Grove.defaultContainer.resolve() + @Resolve var testClass2: TestProtocol XCTAssertEqual(testClass.value, "grove") } /// Tests registering a class as a protocol and resolving it as a protocol. func testClassAsProtocolRegistration() { - Grove.defaultContainer.register(TestClass.init, type: TestProtocol.self) + Grove.defaultContainer.register(as: TestProtocol.self, TestClass.init) @Resolve var testClass: TestProtocol XCTAssertEqual(testClass.value, 0) @@ -37,7 +39,7 @@ final class GroveTests: XCTestCase { /// Tests registering a class using the transient lifetime scope func testTransientScope() { - Grove.defaultContainer.register(TestClass.init, type: TestProtocol.self, scope: .transient) + Grove.defaultContainer.register(as: TestProtocol.self, scope: .transient, TestClass.init) @Resolve var testClass1: TestProtocol testClass1.increment() @@ -45,13 +47,13 @@ final class GroveTests: XCTestCase { testClass1.increment() XCTAssertEqual(testClass1.value, 3) - let testClass2: TestProtocol = Grove.defaultContainer.resolve() + @Resolve var testClass2: TestProtocol XCTAssertEqual(testClass2.value, 0) } /// Tests registering a class using the singleton lifetime scope func testSingletonScope() { - Grove.defaultContainer.register(TestClass.init, type: TestProtocol.self, scope: .singleton) + Grove.defaultContainer.register(as: TestProtocol.self, scope: .singleton, TestClass.init) @Resolve var testClass1: TestProtocol testClass1.increment() diff --git a/Tests/GroveTests/GroveValueTypeDependencyTests.swift b/Tests/GroveTests/GroveValueTypeDependencyTests.swift index 4a29897..e1389d9 100644 --- a/Tests/GroveTests/GroveValueTypeDependencyTests.swift +++ b/Tests/GroveTests/GroveValueTypeDependencyTests.swift @@ -28,13 +28,13 @@ final class GroveValueTypeDependencyTests: XCTestCase { func testDirectTypeRegistration() { Grove.defaultContainer.register(value: NotProtocolConformingTestEnum.b) - let testEnum: NotProtocolConformingTestEnum = Grove.defaultContainer.resolve() + @Resolve var testEnum: NotProtocolConformingTestEnum XCTAssertEqual(testEnum, .b) } /// Tests registering a value type as a protocol and resolving it as a protocol. func testValueTypeAsProtocolRegistration() { - Grove.defaultContainer.register(value: TestEnum.v, type: TestEnumProtocol.self) + Grove.defaultContainer.register(as: TestEnumProtocol.self, value: TestEnum.v) @Resolve var testEnum: TestEnumProtocol XCTAssertEqual(testEnum.value, "v")