From 49e75679f194bdf9a0e0f8cc3c7ff7c8422b72ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B2=D0=BB=D0=B5=D0=B2=20=D0=90=D0=BB=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20=D0=95=D0=B2=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D1=8C=D0=B5=D0=B2=D0=B8=D1=87?= Date: Thu, 27 Sep 2018 14:04:57 +0700 Subject: [PATCH] Support arguments for providers --- CHANGELOG.md | 4 + DITranquillity.podspec | 2 +- Sources/Core/Private/ProtocolMagic.swift | 2 +- Sources/Core/Private/Resolver.swift | 2 +- Sources/Extensions/SwiftLazy.swift | 108 +++++++++++++++++- .../DITranquillityTests_SwiftLazy.swift | 75 ++++++++++++ 6 files changed, 188 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 946907bc..e8060912 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v3.5.1 +* Support arguments for providers +* Add empty Lazy/Provider initialization with fatalError + # v3.5.0 * Support container Hierarchy diff --git a/DITranquillity.podspec b/DITranquillity.podspec index 16a5d722..27b12850 100644 --- a/DITranquillity.podspec +++ b/DITranquillity.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'DITranquillity' - s.version = '3.5.0' + s.version = '3.5.1' s.summary = 'DITranquillity - Dependency injection for iOS/macOS/tvOS (Swift) ' s.description = <<-DESC diff --git a/Sources/Core/Private/ProtocolMagic.swift b/Sources/Core/Private/ProtocolMagic.swift index d4e7b424..4a8d98dd 100644 --- a/Sources/Core/Private/ProtocolMagic.swift +++ b/Sources/Core/Private/ProtocolMagic.swift @@ -23,7 +23,7 @@ class Weak { /// Delay types (lazy, provider) protocol DelayMaker: WrappedType { - init(_ factory: @escaping () -> Any?) + init(_ container: DIContainer, _ factory: @escaping () -> Any?) } ////// For remove optional type diff --git a/Sources/Core/Private/Resolver.swift b/Sources/Core/Private/Resolver.swift index 7c3f84e5..e84be0da 100644 --- a/Sources/Core/Private/Resolver.swift +++ b/Sources/Core/Private/Resolver.swift @@ -166,7 +166,7 @@ class Resolver { if let delayMaker = asDelayMaker(type) { let saveGraph = cache.graph - return delayMaker.init({ () -> Any? in + return delayMaker.init(container, { () -> Any? in return self.mutex.sync { self.cache.graph = saveGraph return self.make(by: type, isMany: isMany, components: components, use: object) diff --git a/Sources/Extensions/SwiftLazy.swift b/Sources/Extensions/SwiftLazy.swift index 7b96b0aa..575234ad 100644 --- a/Sources/Extensions/SwiftLazy.swift +++ b/Sources/Extensions/SwiftLazy.swift @@ -9,7 +9,14 @@ import SwiftLazy extension Lazy: DelayMaker { - convenience init(_ factory: @escaping () -> Any?) { + public convenience init(file: String = #file, line: UInt = #line) { + self.init { () -> Value in + let name = (file as NSString).lastPathComponent + fatalError("Please inject this property from DI in file: \(name) on line: \(line). Lazy type: \(Value.self) ") + } + } + + convenience init(_ container: DIContainer, _ factory: @escaping () -> Any?) { self.init { () -> Value in return gmake(by: factory()) } @@ -21,7 +28,14 @@ extension Lazy: DelayMaker { } extension Provider: DelayMaker { - convenience init(_ factory: @escaping () -> Any?) { + public convenience init(file: String = #file, line: UInt = #line) { + self.init { () -> Value in + let name = (file as NSString).lastPathComponent + fatalError("Please inject this property from DI in file: \(name) on line: \(line). Provider type: \(Value.self) ") + } + } + + convenience init(_ container: DIContainer, _ factory: @escaping () -> Any?) { self.init { () -> Value in return gmake(by: factory()) } @@ -32,3 +46,93 @@ extension Provider: DelayMaker { } } +// Providers with args +extension Provider1: DelayMaker { + public convenience init(file: String = #file, line: UInt = #line) { + self.init { _ -> Value in + let name = (file as NSString).lastPathComponent + fatalError("Please inject this property from DI in file: \(name) on line: \(line). Provider type: \(Value.self) ") + } + } + + static var type: DIAType { return Value.self } + + convenience init(_ container: DIContainer, _ factory: @escaping () -> Any?) { + self.init { (arg1) -> Value in + container.extensions(for: Value.self)?.setArgs(arg1) + return gmake(by: factory()) + } + } +} + +extension Provider2: DelayMaker { + public convenience init(file: String = #file, line: UInt = #line) { + self.init { _, _ -> Value in + let name = (file as NSString).lastPathComponent + fatalError("Please inject this property from DI in file: \(name) on line: \(line). Provider type: \(Value.self) ") + } + } + + static var type: DIAType { return Value.self } + + convenience init(_ container: DIContainer, _ factory: @escaping () -> Any?) { + self.init { (arg1, arg2) -> Value in + container.extensions(for: Value.self)?.setArgs(arg1, arg2) + return gmake(by: factory()) + } + } +} + +extension Provider3: DelayMaker { + public convenience init(file: String = #file, line: UInt = #line) { + self.init { _, _, _ -> Value in + let name = (file as NSString).lastPathComponent + fatalError("Please inject this property from DI in file: \(name) on line: \(line). Provider type: \(Value.self) ") + } + } + + static var type: DIAType { return Value.self } + + convenience init(_ container: DIContainer, _ factory: @escaping () -> Any?) { + self.init { (arg1, arg2, arg3) -> Value in + container.extensions(for: Value.self)?.setArgs(arg1, arg2, arg3) + return gmake(by: factory()) + } + } +} + +extension Provider4: DelayMaker { + public convenience init(file: String = #file, line: UInt = #line) { + self.init { _, _, _, _ -> Value in + let name = (file as NSString).lastPathComponent + fatalError("Please inject this property from DI in file: \(name) on line: \(line). Provider type: \(Value.self) ") + } + } + + static var type: DIAType { return Value.self } + + convenience init(_ container: DIContainer, _ factory: @escaping () -> Any?) { + self.init { (arg1, arg2, arg3, arg4) -> Value in + container.extensions(for: Value.self)?.setArgs(arg1, arg2, arg3, arg4) + return gmake(by: factory()) + } + } +} + +extension Provider5: DelayMaker { + public convenience init(file: String = #file, line: UInt = #line) { + self.init { _, _, _, _, _ -> Value in + let name = (file as NSString).lastPathComponent + fatalError("Please inject this property from DI in file: \(name) on line: \(line). Provider type: \(Value.self) ") + } + } + + static var type: DIAType { return Value.self } + + convenience init(_ container: DIContainer, _ factory: @escaping () -> Any?) { + self.init { (arg1, arg2, arg3, arg4, arg5) -> Value in + container.extensions(for: Value.self)?.setArgs(arg1, arg2, arg3, arg4, arg5) + return gmake(by: factory()) + } + } +} diff --git a/Tests/DITranquillityTest/DITranquillityTests_SwiftLazy.swift b/Tests/DITranquillityTest/DITranquillityTests_SwiftLazy.swift index 8e8dfd17..c2a45c11 100644 --- a/Tests/DITranquillityTest/DITranquillityTests_SwiftLazy.swift +++ b/Tests/DITranquillityTest/DITranquillityTests_SwiftLazy.swift @@ -47,6 +47,33 @@ private class ProviderInjectA { var inject: Provider! } +private class A1 { + fileprivate let value1: Int + init(_ value1: Int) { self.value1 = value1 } +} +private class Provider1InjectA { + var inject: Provider1 = Provider1() +} + +private class A2 { + fileprivate let value1: Int + fileprivate let value2: Double + init(_ value1: Int, _ value2: Double) { self.value1 = value1; self.value2 = value2 } +} +private class Provider2InjectA { + var inject: Provider2 = Provider2() +} + +private class A3 { + fileprivate let value1: Int + fileprivate let value2: Double + fileprivate let value3: String + init(_ value1: Int, _ value2: Double, _ value3: String) { self.value1 = value1; self.value2 = value2; self.value3 = value3 } +} +private class Provider3InjectA { + var inject: Provider3 = Provider3() +} + class DITranquillityTests_SwiftLazy: XCTestCase { override func setUp() { @@ -239,4 +266,52 @@ class DITranquillityTests_SwiftLazy: XCTestCase { XCTAssertEqual(test.inject.value.foo(), "foo") } + func test11_Provider1() { + let container = DIContainer() + + container.register1{ A1(arg($0)) } + + container.register(Provider1InjectA.init) + .injection(\.inject) + + let test: Provider1InjectA = *container + + + XCTAssertEqual(test.inject.value(10).value1, 10) + XCTAssertEqual(test.inject.value(12).value1, 12) + } + + func test11_Provider2() { + let container = DIContainer() + + container.register{ A2(arg($0), arg($1)) } + + container.register(Provider2InjectA.init) + .injection(\.inject) + + let test: Provider2InjectA = *container + + + let a = test.inject.value(10, 15.0) + XCTAssertEqual(a.value1, 10) + XCTAssertEqual(a.value2, 15.0) + } + + func test11_Provider3() { + let container = DIContainer() + + container.register{ A3(arg($0), arg($1), arg($2)) } + + container.register(Provider3InjectA.init) + .injection(\.inject) + + let test: Provider3InjectA = *container + + + let a = test.inject.value(11, 12.0, "a") + XCTAssertEqual(a.value1, 11) + XCTAssertEqual(a.value2, 12.0) + XCTAssertEqual(a.value3, "a") + } + }