Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| feb5064b93 | |||
| 184e1f4543 | |||
| 8be1139114 | |||
| afc8e49b18 | |||
| 333fa96b62 | |||
| d611ea240e | |||
| ee16baacfc | |||
| b4221e25a1 | |||
| 0edd3747e8 | |||
| 2708f7e434 |
@@ -1,5 +1,16 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 3.1.0
|
||||
|
||||
#### New
|
||||
|
||||
* Added name for the first runtime argument in `resolve(tag:withArguments: … )` methods to make more clear separation between tag and factory runtime arguments.
|
||||
|
||||
#### Depreciations
|
||||
|
||||
* `resolve(tag:_: … )` methods are deprecated in favor of those new `resolve(tag:withArguments: … )` methods.
|
||||
* Deprecated `register(tag:instance:)` method in favor of `register(.Singleton) { … }`.
|
||||
|
||||
## 3.0.0
|
||||
|
||||
* Added support for factories with up to six runtime arguments.
|
||||
@@ -7,6 +18,27 @@
|
||||
* Parameter `tag` is now named in all register/resolve methods.
|
||||
* Playground added to project.
|
||||
[#10](https://github.com/AliSoftware/Dip/pull/10), [@ilyapuchka](https://github.com/ilyapuchka)
|
||||
|
||||
### Note on migration from 2.0.0 to 3.0.0:
|
||||
|
||||
If you used tags to register and resolve your components you have to add `tag` name for tag parameter. Don't forget to add it both in `register` and `resolve` methods. If you forget to add it in `resolve` call then tag value will be treated as first runtime argument for a factory, but there is no such factory registerd, so resolve will fail.
|
||||
|
||||
**Example**:
|
||||
|
||||
This code:
|
||||
|
||||
```swift
|
||||
container.register("some tag") { SomeClass() as SomeProtocol }
|
||||
container.resolve("some tag") as SomeProtocol
|
||||
```
|
||||
|
||||
becomes this:
|
||||
|
||||
```swift
|
||||
container.register(tag: "some tag") { SomeClass() as SomeProtocol }
|
||||
container.resolve(tag: "some tag") as SomeProtocol
|
||||
```
|
||||
|
||||
|
||||
## 2.0.0
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "Dip"
|
||||
s.version = "3.0.0"
|
||||
s.version = "3.1.0"
|
||||
s.summary = "A simple Dependency Resolver: Dependency Injection using Protocol resolution."
|
||||
|
||||
s.description = <<-DESC
|
||||
|
||||
@@ -253,7 +253,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 3.1.0;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@@ -271,7 +271,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -301,7 +301,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 3.1.0;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
@@ -313,7 +313,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
||||
+7
-3
@@ -81,8 +81,8 @@ public class DependencyContainer {
|
||||
|
||||
- note: You must cast the factory return type to the protocol you want to register it with (e.g `MyClass() as MyAPI`)
|
||||
*/
|
||||
public func register<T>(tag tag: Tag? = nil, factory: ()->T) -> DefinitionOf<T> {
|
||||
return register(tag: tag, factory: factory, scope: .Prototype) as DefinitionOf<T>
|
||||
public func register<T>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: ()->T) -> DefinitionOf<T> {
|
||||
return register(tag: tag, factory: factory, scope: scope) as DefinitionOf<T>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,7 +92,11 @@ public class DependencyContainer {
|
||||
- parameter instance: The instance to register, with return type of protocol you want to register it for
|
||||
|
||||
- note: You must cast the instance to the protocol you want to register it with (e.g `MyClass() as MyAPI`)
|
||||
*/
|
||||
|
||||
**Deprecated**: Use `register(.Singleton){}` method instead to define singleton scope.
|
||||
*/
|
||||
|
||||
@available(*, deprecated, message="Use `register(.Singleton){}` method instead to define singleton scope.")
|
||||
public func register<T>(tag tag: Tag? = nil, @autoclosure(escaping) instance factory: ()->T) -> DefinitionOf<T> {
|
||||
return register(tag: tag, factory: { factory() }, scope: .Singleton)
|
||||
}
|
||||
|
||||
@@ -43,8 +43,8 @@ extension DependencyContainer {
|
||||
|
||||
- seealso: `register(tag:factory:scope:)`
|
||||
*/
|
||||
public func register<T, Arg1>(tag tag: Tag? = nil, factory: (Arg1) -> T) -> DefinitionOf<T> {
|
||||
return register(tag: tag, factory: factory, scope: .Prototype) as DefinitionOf<T>
|
||||
public func register<T, Arg1>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1) -> T) -> DefinitionOf<T> {
|
||||
return register(tag: tag, factory: factory, scope: scope) as DefinitionOf<T>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,6 +56,12 @@ extension DependencyContainer {
|
||||
|
||||
- seealso: `resolve(tag:)`
|
||||
*/
|
||||
public func resolve<T, Arg1>(tag tag: Tag? = nil, withArguments arg1: Arg1) -> T {
|
||||
return resolve(tag: tag) { (factory: (Arg1) -> T) in factory(arg1) }
|
||||
}
|
||||
|
||||
///**Deprecated** Use `resolve(tag:withArguments:)` method instead.
|
||||
@available(*, deprecated, message="Use `resolve(tag:withArguments:)` method instead.")
|
||||
public func resolve<T, Arg1>(tag tag: Tag? = nil, _ arg1: Arg1) -> T {
|
||||
return resolve(tag: tag) { (factory: (Arg1) -> T) in factory(arg1) }
|
||||
}
|
||||
@@ -63,55 +69,85 @@ extension DependencyContainer {
|
||||
// MARK: 2 Runtime Arguments
|
||||
|
||||
/// - seealso: `register(:factory:scope:)`
|
||||
public func register<T, Arg1, Arg2>(tag tag: Tag? = nil, factory: (Arg1, Arg2) -> T) -> DefinitionOf<T> {
|
||||
return register(tag: tag, factory: factory, scope: .Prototype) as DefinitionOf<T>
|
||||
public func register<T, Arg1, Arg2>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2) -> T) -> DefinitionOf<T> {
|
||||
return register(tag: tag, factory: factory, scope: scope) as DefinitionOf<T>
|
||||
}
|
||||
|
||||
/// - seealso: `resolve(tag:_:)`
|
||||
public func resolve<T, Arg1, Arg2>(tag tag: Tag? = nil, withArguments arg1: Arg1, _ arg2: Arg2) -> T {
|
||||
return resolve(tag: tag) { (factory: (Arg1, Arg2) -> T) in factory(arg1, arg2) }
|
||||
}
|
||||
|
||||
///**Deprecated** Use `resolve(tag:withArguments:_:)` method instead.
|
||||
@available(*, deprecated, message="Use `resolve(tag:withArguments:_:)` method instead.")
|
||||
public func resolve<T, Arg1, Arg2>(tag tag: Tag? = nil, _ arg1: Arg1, _ arg2: Arg2) -> T {
|
||||
return resolve(tag: tag) { (factory: (Arg1, Arg2) -> T) in factory(arg1, arg2) }
|
||||
}
|
||||
|
||||
// MARK: 3 Runtime Arguments
|
||||
|
||||
public func register<T, Arg1, Arg2, Arg3>(tag tag: Tag? = nil, factory: (Arg1, Arg2, Arg3) -> T) -> DefinitionOf<T> {
|
||||
return register(tag: tag, factory: factory, scope: .Prototype) as DefinitionOf<T>
|
||||
public func register<T, Arg1, Arg2, Arg3>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3) -> T) -> DefinitionOf<T> {
|
||||
return register(tag: tag, factory: factory, scope: scope) as DefinitionOf<T>
|
||||
}
|
||||
|
||||
/// - seealso: `resolve(tag:_:)`
|
||||
/// - seealso: `resolve(tag:withArguments:)`
|
||||
public func resolve<T, Arg1, Arg2, Arg3>(tag tag: Tag? = nil, withArguments arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3) -> T {
|
||||
return resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3) -> T) in factory(arg1, arg2, arg3) }
|
||||
}
|
||||
|
||||
///**Deprecated** Use `resolve(tag:withArguments:_:_:)` method instead.
|
||||
@available(*, deprecated, message="Use `resolve(tag:withArguments:_:_:)` method instead.")
|
||||
public func resolve<T, Arg1, Arg2, Arg3>(tag tag: Tag? = nil, _ arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3) -> T {
|
||||
return resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3) -> T) in factory(arg1, arg2, arg3) }
|
||||
}
|
||||
|
||||
// MARK: 4 Runtime Arguments
|
||||
|
||||
public func register<T, Arg1, Arg2, Arg3, Arg4>(tag tag: Tag? = nil, factory: (Arg1, Arg2, Arg3, Arg4) -> T) -> DefinitionOf<T> {
|
||||
return register(tag: tag, factory: factory, scope: .Prototype) as DefinitionOf<T>
|
||||
public func register<T, Arg1, Arg2, Arg3, Arg4>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3, Arg4) -> T) -> DefinitionOf<T> {
|
||||
return register(tag: tag, factory: factory, scope: scope) as DefinitionOf<T>
|
||||
}
|
||||
|
||||
/// - seealso: `resolve(tag:_:)`
|
||||
/// - seealso: `resolve(tag:withArguments:)`
|
||||
public func resolve<T, Arg1, Arg2, Arg3, Arg4>(tag tag: Tag? = nil, withArguments arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3, _ arg4: Arg4) -> T {
|
||||
return resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4) -> T) in factory(arg1, arg2, arg3, arg4) }
|
||||
}
|
||||
|
||||
///**Deprecated** Use `resolve(tag:withArguments:_:_:_:)` method instead.
|
||||
@available(*, deprecated, message="Use `resolve(tag:withArguments:_:_:_:)` method instead.")
|
||||
public func resolve<T, Arg1, Arg2, Arg3, Arg4>(tag tag: Tag? = nil, _ arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3, _ arg4: Arg4) -> T {
|
||||
return resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4) -> T) in factory(arg1, arg2, arg3, arg4) }
|
||||
}
|
||||
|
||||
// MARK: 4 Runtime Arguments
|
||||
// MARK: 5 Runtime Arguments
|
||||
|
||||
public func register<T, Arg1, Arg2, Arg3, Arg4, Arg5>(tag tag: Tag? = nil, factory: (Arg1, Arg2, Arg3, Arg4, Arg5) -> T) -> DefinitionOf<T> {
|
||||
return register(tag: tag, factory: factory, scope: .Prototype) as DefinitionOf<T>
|
||||
public func register<T, Arg1, Arg2, Arg3, Arg4, Arg5>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3, Arg4, Arg5) -> T) -> DefinitionOf<T> {
|
||||
return register(tag: tag, factory: factory, scope: scope) as DefinitionOf<T>
|
||||
}
|
||||
|
||||
/// - seealso: `resolve(tag:_:)`
|
||||
/// - seealso: `resolve(tag:withArguments:)`
|
||||
public func resolve<T, Arg1, Arg2, Arg3, Arg4, Arg5>(tag tag: Tag? = nil, withArguments arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3, _ arg4: Arg4, _ arg5: Arg5) -> T {
|
||||
return resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4, Arg5) -> T) in factory(arg1, arg2, arg3, arg4, arg5) }
|
||||
}
|
||||
|
||||
///**Deprecated** Use `resolve(tag:withArguments:_:_:_:_:)` method instead.
|
||||
@available(*, deprecated, message="Use `resolve(tag:withArguments:_:_:_:_:)` method instead.")
|
||||
public func resolve<T, Arg1, Arg2, Arg3, Arg4, Arg5>(tag tag: Tag? = nil, _ arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3, _ arg4: Arg4, _ arg5: Arg5) -> T {
|
||||
return resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4, Arg5) -> T) in factory(arg1, arg2, arg3, arg4, arg5) }
|
||||
}
|
||||
|
||||
// MARK: 5 Runtime Arguments
|
||||
// MARK: 6 Runtime Arguments
|
||||
|
||||
public func register<T, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6>(tag tag: Tag? = nil, factory: (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) -> T) -> DefinitionOf<T> {
|
||||
return register(tag: tag, factory: factory, scope: .Prototype) as DefinitionOf<T>
|
||||
public func register<T, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) -> T) -> DefinitionOf<T> {
|
||||
return register(tag: tag, factory: factory, scope: scope) as DefinitionOf<T>
|
||||
}
|
||||
|
||||
/// - seealso: `resolve(tag:_:)`
|
||||
/// - seealso: `resolve(tag:withArguments:)`
|
||||
public func resolve<T, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6>(tag tag: Tag? = nil, withArguments arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3, _ arg4: Arg4, _ arg5: Arg5, _ arg6: Arg6) -> T {
|
||||
return resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) -> T) in factory(arg1, arg2, arg3, arg4, arg5, arg6) }
|
||||
}
|
||||
|
||||
///**Deprecated** Use `resolve(tag:withArguments:_:_:_:_:_:)` method instead.
|
||||
@available(*, deprecated, message="Use `resolve(tag:withArguments:_:_:_:_:_:)` method instead.")
|
||||
public func resolve<T, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6>(tag tag: Tag? = nil, _ arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3, _ arg4: Arg4, _ arg5: Arg5, _ arg6: Arg6) -> T {
|
||||
return resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) -> T) in factory(arg1, arg2, arg3, arg4, arg5, arg6) }
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ class DipTests: XCTestCase {
|
||||
|
||||
func testThatItReusesInstanceRegisteredAsSingleton() {
|
||||
//given
|
||||
container.register(instance: ServiceImp1() as Service)
|
||||
container.register(.Singleton) { ServiceImp1() as Service }
|
||||
|
||||
//when
|
||||
let service1 = container.resolve() as Service
|
||||
|
||||
@@ -40,7 +40,7 @@ class RuntimeArgumentsTests: XCTestCase {
|
||||
}
|
||||
|
||||
//when
|
||||
let service = container.resolve(arg1) as Service
|
||||
let service = container.resolve(withArguments: arg1) as Service
|
||||
|
||||
//then
|
||||
XCTAssertTrue(service is ServiceImp1)
|
||||
@@ -56,7 +56,7 @@ class RuntimeArgumentsTests: XCTestCase {
|
||||
}
|
||||
|
||||
//when
|
||||
let service = container.resolve(arg1, arg2) as Service
|
||||
let service = container.resolve(withArguments: arg1, arg2) as Service
|
||||
|
||||
//then
|
||||
XCTAssertTrue(service is ServiceImp1)
|
||||
@@ -72,7 +72,7 @@ class RuntimeArgumentsTests: XCTestCase {
|
||||
}
|
||||
|
||||
//when
|
||||
let service = container.resolve(arg1, arg2, arg3) as Service
|
||||
let service = container.resolve(withArguments: arg1, arg2, arg3) as Service
|
||||
|
||||
//then
|
||||
XCTAssertTrue(service is ServiceImp1)
|
||||
@@ -89,7 +89,7 @@ class RuntimeArgumentsTests: XCTestCase {
|
||||
}
|
||||
|
||||
//when
|
||||
let service = container.resolve(arg1, arg2, arg3, arg4) as Service
|
||||
let service = container.resolve(withArguments: arg1, arg2, arg3, arg4) as Service
|
||||
|
||||
//then
|
||||
XCTAssertTrue(service is ServiceImp1)
|
||||
@@ -107,7 +107,7 @@ class RuntimeArgumentsTests: XCTestCase {
|
||||
}
|
||||
|
||||
//when
|
||||
let service = container.resolve(arg1, arg2, arg3, arg4, arg5) as Service
|
||||
let service = container.resolve(withArguments: arg1, arg2, arg3, arg4, arg5) as Service
|
||||
|
||||
//then
|
||||
XCTAssertTrue(service is ServiceImp1)
|
||||
@@ -126,7 +126,7 @@ class RuntimeArgumentsTests: XCTestCase {
|
||||
}
|
||||
|
||||
//when
|
||||
let service = container.resolve(arg1, arg2, arg3, arg4, arg5, arg6) as Service
|
||||
let service = container.resolve(withArguments: arg1, arg2, arg3, arg4, arg5, arg6) as Service
|
||||
|
||||
//then
|
||||
XCTAssertTrue(service is ServiceImp1)
|
||||
@@ -139,8 +139,8 @@ class RuntimeArgumentsTests: XCTestCase {
|
||||
container.register { (a1: Int, a2: Int) in ServiceImp2() as Service }
|
||||
|
||||
//when
|
||||
let service1 = container.resolve(arg1) as Service
|
||||
let service2 = container.resolve(arg1, arg2) as Service
|
||||
let service1 = container.resolve(withArguments: arg1) as Service
|
||||
let service2 = container.resolve(withArguments: arg1, arg2) as Service
|
||||
|
||||
//then
|
||||
XCTAssertTrue(service1 is ServiceImp1)
|
||||
@@ -154,8 +154,8 @@ class RuntimeArgumentsTests: XCTestCase {
|
||||
container.register { (a1: String) in ServiceImp2() as Service }
|
||||
|
||||
//when
|
||||
let service1 = container.resolve(arg1) as Service
|
||||
let service2 = container.resolve(arg2) as Service
|
||||
let service1 = container.resolve(withArguments: arg1) as Service
|
||||
let service2 = container.resolve(withArguments: arg2) as Service
|
||||
|
||||
//then
|
||||
XCTAssertTrue(service1 is ServiceImp1)
|
||||
@@ -169,8 +169,8 @@ class RuntimeArgumentsTests: XCTestCase {
|
||||
container.register { (a1: String, a2: Int) in ServiceImp2() as Service }
|
||||
|
||||
//when
|
||||
let service1 = container.resolve(arg1, arg2) as Service
|
||||
let service2 = container.resolve(arg2, arg1) as Service
|
||||
let service1 = container.resolve(withArguments: arg1, arg2) as Service
|
||||
let service2 = container.resolve(withArguments: arg2, arg1) as Service
|
||||
|
||||
//then
|
||||
XCTAssertTrue(service1 is ServiceImp1)
|
||||
@@ -181,11 +181,11 @@ class RuntimeArgumentsTests: XCTestCase {
|
||||
//given
|
||||
let arg1 = 1, arg2 = 2
|
||||
container.register { (a1: Int, a2: Int) in ServiceImp1() as Service }
|
||||
let service1 = container.resolve(arg1, arg2) as Service
|
||||
let service1 = container.resolve(withArguments: arg1, arg2) as Service
|
||||
|
||||
//when
|
||||
container.register { (a1: Int, a2: Int) in ServiceImp2() as Service }
|
||||
let service2 = container.resolve(arg1, arg2) as Service
|
||||
let service2 = container.resolve(withArguments: arg1, arg2) as Service
|
||||
|
||||
//then
|
||||
XCTAssertTrue(service1 is ServiceImp1)
|
||||
@@ -201,11 +201,11 @@ class RuntimeArgumentsTests: XCTestCase {
|
||||
|
||||
//when
|
||||
let url: NSURL = NSURL(string: "http://example.com")!
|
||||
let service1 = container.resolve(80, url) as Service
|
||||
let service2 = container.resolve(80, NSURL(string: "http://example.com")) as Service
|
||||
let service1 = container.resolve(withArguments: 80, url) as Service
|
||||
let service2 = container.resolve(withArguments: 80, NSURL(string: "http://example.com")) as Service
|
||||
|
||||
let service3 = container.resolve(80, NSURL(string: "http://example.com")! as NSURL!) as Service
|
||||
let service4 = container.resolve(80, NSURL(string: "http://example.com")!) as Service
|
||||
let service3 = container.resolve(withArguments: 80, NSURL(string: "http://example.com")! as NSURL!) as Service
|
||||
let service4 = container.resolve(withArguments: 80, NSURL(string: "http://example.com")!) as Service
|
||||
|
||||
//then
|
||||
XCTAssertEqual(service1.getServiceName(), name1)
|
||||
|
||||
@@ -18,10 +18,10 @@ container.register { (port: Int, url: NSURL?) in ServiceImp3(name: "3", baseURL:
|
||||
container.register { (port: Int, url: NSURL!) in ServiceImp3(name: "4", baseURL: url, port: port) as Service }
|
||||
|
||||
let url: NSURL = NSURL(string: "http://example.com")!
|
||||
let service1 = container.resolve(url, 80) as Service
|
||||
let service2 = container.resolve(80, url) as Service
|
||||
let service3 = container.resolve(80, NSURL(string: "http://example.com")) as Service
|
||||
let service4 = container.resolve(80, NSURL(string: "http://example.com")! as NSURL!) as Service
|
||||
let service1 = container.resolve(withArguments: url, 80) as Service
|
||||
let service2 = container.resolve(withArguments: 80, url) as Service
|
||||
let service3 = container.resolve(withArguments: 80, NSURL(string: "http://example.com")) as Service
|
||||
let service4 = container.resolve(withArguments: 80, NSURL(string: "http://example.com")! as NSURL!) as Service
|
||||
|
||||
(service1 as! ServiceImp3).name
|
||||
(service2 as! ServiceImp3).name
|
||||
|
||||
@@ -54,13 +54,15 @@ The next paragraphs give you an overview of the Usage of _Dip_ directly, but if
|
||||
|
||||
## Usage
|
||||
|
||||
### Register instances and instance factories
|
||||
*See [CHANGELOG.md](https://github.com/AliSoftware/Dip/blob/master/CHANGELOG.md) for instructions to migrate from 2.0.0 to 3.0.0*
|
||||
|
||||
First, create a `DependencyContainer` and use it to register instances and factories with protocols, using those methods:
|
||||
### Register instance factories
|
||||
|
||||
* `register(instance: _)` will register a singleton instance with a given protocol.
|
||||
* `register(factory: _)` will register an instance factory — which generates a new instance each time you `resolve()`.
|
||||
* You need **cast the instance to the protocol type** you want to register it with (e.g. `register(instance: PlistUsersProvider() as UsersListProviderType)`).
|
||||
First, create a `DependencyContainer` and use it to register instance factories with protocols, using those methods:
|
||||
|
||||
* `register(.Singleton) { … }` will register a singleton instance with a given protocol.
|
||||
* `register(.Prototype) { … }` (or just `register { … }`) will register an instance factory which generates a new instance each time you `resolve()`.
|
||||
* You need **cast the instance to the protocol type** you want to register it with (e.g. `register { PlistUsersProvider() as UsersListProviderType }`).
|
||||
|
||||
Typically, to register your dependencies as early as possible in your app life-cycle, you will declare a `let dip: DependencyContainer = { … }()` somewhere (for example [in a dedicated `.swift` file](https://github.com/AliSoftware/Dip/blob/master/Example/DipSampleApp/DependencyContainers.swift#L22-L27)). In your (non-hosted, standalone) unit tests, you'll probably [reset them in your `func setUp()`](https://github.com/AliSoftware/Dip/blob/master/Example/Tests/SWAPIPersonProviderTests.swift#L17-L21) instead.
|
||||
|
||||
@@ -68,7 +70,19 @@ Typically, to register your dependencies as early as possible in your app life-c
|
||||
|
||||
* `resolve()` will return a new instance matching the requested protocol.
|
||||
* Explicitly specify the return type of `resolve` so that Swift's type inference knows which protocol you're trying to resolve.
|
||||
* If that protocol was registered as a singleton instance (using `register(instance: …)`, the same instance will be returned each time you call `resolve()` for this protocol type. Otherwise, the instance factory will generate a new instance each time.
|
||||
|
||||
```swift
|
||||
container.register { ServiceImp() as Service }
|
||||
let service = container.resolve() as Service
|
||||
```
|
||||
|
||||
### Scopes
|
||||
|
||||
Dip provides two _scopes_ that you can use to register dependencies:
|
||||
|
||||
* The `.Prototype` scope will make the `DependencyContainer` resolve your type as __a new instance every time__ you call `resolve`. It's a default scope.
|
||||
* The `.Singleton` scope will make the `DependencyContainer` retain the instance once resolved the first time, and reuse it in the next calls to `resolve` during the container lifetime.
|
||||
|
||||
|
||||
### Using block-based initialization
|
||||
|
||||
@@ -80,8 +94,8 @@ It may not seem to provide much, but given the fact that `DependencyContainers`
|
||||
let dip: DependencyContainer = {
|
||||
let dip = DependencyContainer()
|
||||
|
||||
dip.register(instance: ProductionEnvironment(analytics: true) as EnvironmentType)
|
||||
dip.register(instance: WebService() as WebServiceAPI)
|
||||
dip.register { ProductionEnvironment(analytics: true) as EnvironmentType }
|
||||
dip.register { WebService() as WebServiceAPI }
|
||||
|
||||
return dip
|
||||
}()
|
||||
@@ -91,8 +105,8 @@ You can instead write this exact equivalent code, which is more compact, and ind
|
||||
|
||||
```swift
|
||||
let dip = DependencyContainer { dip in
|
||||
dip.register(instance: ProductionEnvironment(analytics: true) as EnvironmentType)
|
||||
dip.register(instance: WebService() as WebServiceAPI)
|
||||
dip.register { ProductionEnvironment(analytics: true) as EnvironmentType }
|
||||
dip.register { WebService() as WebServiceAPI }
|
||||
}
|
||||
```
|
||||
|
||||
@@ -111,8 +125,8 @@ enum WebService: String {
|
||||
}
|
||||
|
||||
let wsDependencies = DependencyContainer() { dip in
|
||||
dip.register(tag: WebService.PersonWS.tag, instance: URLSessionNetworkLayer(baseURL: "http://prod.myapi.com/api/")! as NetworkLayer)
|
||||
dip.register(tag: WebService.StashipWS.tag, instance: URLSessionNetworkLayer(baseURL: "http://dev.myapi.com/api/")! as NetworkLayer)
|
||||
dip.register(tag: WebService.PersonWS.tag) { URLSessionNetworkLayer(baseURL: "http://prod.myapi.com/api/")! as NetworkLayer }
|
||||
dip.register(tag: WebService.StashipWS.tag) { URLSessionNetworkLayer(baseURL: "http://dev.myapi.com/api/")! as NetworkLayer }
|
||||
}
|
||||
|
||||
let networkLayer = dip.resolve(tag: WebService.PersonWS.tag) as NetworkLayer
|
||||
@@ -129,19 +143,19 @@ let webServices = DependencyContainer() { webServices in
|
||||
webServices.register { (port: Int, url: NSURL?) in WebServiceImp3(url!, port: port) as WebServiceAPI }
|
||||
}
|
||||
|
||||
let service1 = webServices.resolve(NSURL(string: "http://example.url")!, 80) as WebServiceAPI // service1 is WebServiceImp1
|
||||
let service2 = webServices.resolve(80, NSURL(string: "http://example.url")!) as WebServiceAPI // service2 is WebServiceImp2
|
||||
let service3 = webServices.resolve(80, NSURL(string: "http://example.url")) as WebServiceAPI // service3 is WebServiceImp3
|
||||
let service1 = webServices.resolve(withArguments: NSURL(string: "http://example.url")!, 80) as WebServiceAPI // service1 is WebServiceImp1
|
||||
let service2 = webServices.resolve(withArguments: 80, NSURL(string: "http://example.url")!) as WebServiceAPI // service2 is WebServiceImp2
|
||||
let service3 = webServices.resolve(withArguments: 80, NSURL(string: "http://example.url")) as WebServiceAPI // service3 is WebServiceImp3
|
||||
|
||||
```
|
||||
Though Dip provides support for up to six runtime arguments out of the box you can extend this number using following code snippet for seven arguments:
|
||||
|
||||
```
|
||||
func register<T, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7>(tag: Tag? = nil, factory: (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) -> T) -> DefinitionOf<T> {
|
||||
return register(tag, factory: factory, scope: .Prototype) as DefinitionOf<T>
|
||||
func register<T, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7>(tag: Tag? = nil, scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) -> T) -> DefinitionOf<T, (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) -> T)> {
|
||||
return registerFactory(tag, scope: .Prototype, factory: factory) as DefinitionOf<T, (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) -> T)>
|
||||
}
|
||||
|
||||
func resolve<T, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7>(tag tag: Tag? = nil, _ arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3, _ arg4: Arg4, _ arg5: Arg5, _ arg6: Arg6, _ arg7: Arg7) -> T {
|
||||
func resolve<T, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7>(tag tag: Tag? = nil, withArguments arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3, _ arg4: Arg4, _ arg5: Arg5, _ arg6: Arg6, _ arg7: Arg7) -> T {
|
||||
return resolve(tag) { (factory: (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) -> T) in factory(arg1, arg2, arg3, arg4, arg5, arg6, arg7) }
|
||||
}
|
||||
|
||||
@@ -155,10 +169,10 @@ Somewhere in your App target, register the dependencies:
|
||||
let dip: DependencyContainer = {
|
||||
let dip = DependencyContainer()
|
||||
let env = ProductionEnvironment(analytics: true)
|
||||
dip.register(instance: env as EnvironmentType)
|
||||
dip.register(instance: WebService() as WebServiceType)
|
||||
dip.register() { name: String in DummyFriendsProvider(user: name) as FriendsProviderType }
|
||||
dip.register(tag: "me") { _: String in PlistFriendsProvider(plist: "myfriends") as FriendsProviderType }
|
||||
dip.register(.Singleton) { env as EnvironmentType }
|
||||
dip.register(.Singleton) { WebService() as WebServiceType }
|
||||
dip.register() { (name: String) in DummyFriendsProvider(user: name) as FriendsProviderType }
|
||||
dip.register(tag: "me") { (_: String) in PlistFriendsProvider(plist: "myfriends") as FriendsProviderType }
|
||||
return dip
|
||||
}
|
||||
```
|
||||
@@ -210,7 +224,7 @@ This sample uses the Star Wars API provided by swapi.co to fetch Star Wars chara
|
||||
## Credits
|
||||
|
||||
This library has been created by [**Olivier Halligon**](olivier@halligon.net).
|
||||
I'd also like to thank **Ilya Puchka** for his big contribution to it, as he added a lot of great features to it.
|
||||
I'd also like to thank [**Ilya Puchka**](https://twitter.com/ilyapuchka) for his big contribution to it, as he added a lot of great features to it.
|
||||
|
||||
**Dip** is available under the **MIT license**. See the `LICENSE` file for more info.
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ private let FAKE_STARSHIPS = false
|
||||
let wsDependencies = DependencyContainer() { dip in
|
||||
|
||||
// Register the NetworkLayer, same for everyone here (but we have the ability to register a different one for a specific WebService if we wanted to)
|
||||
dip.register(instance: URLSessionNetworkLayer(baseURL: "http://swapi.co/api/")! as NetworkLayer)
|
||||
dip.register(.Singleton) { URLSessionNetworkLayer(baseURL: "http://swapi.co/api/")! as NetworkLayer }
|
||||
|
||||
}
|
||||
|
||||
@@ -33,13 +33,13 @@ let providerDependencies = DependencyContainer() { dip in
|
||||
if FAKE_PERSONS {
|
||||
|
||||
// 1) Register the PersonProviderAPI singleton, one generic and one specific for a specific personID
|
||||
dip.register(instance: DummyPilotProvider() as PersonProviderAPI)
|
||||
dip.register(tag: 0, instance: PlistPersonProvider(plist: "mainPilot") as PersonProviderAPI)
|
||||
dip.register(.Singleton) { DummyPilotProvider() as PersonProviderAPI }
|
||||
dip.register(tag: 0, .Singleton) { PlistPersonProvider(plist: "mainPilot") as PersonProviderAPI }
|
||||
|
||||
} else {
|
||||
|
||||
// 1) Register the SWAPIPersonProvider (that hits the real swapi.co WebService)
|
||||
dip.register(instance: SWAPIPersonProvider() as PersonProviderAPI)
|
||||
dip.register(.Singleton) { SWAPIPersonProvider() as PersonProviderAPI }
|
||||
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ let providerDependencies = DependencyContainer() { dip in
|
||||
} else {
|
||||
|
||||
// 2) Register the SWAPIStarshipProvider (that hits the real swapi.co WebService)
|
||||
dip.register(instance: SWAPIStarshipProvider() as StarshipProviderAPI)
|
||||
dip.register(.Singleton) { SWAPIStarshipProvider() as StarshipProviderAPI }
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class SWAPIPersonProviderTests: XCTestCase {
|
||||
|
||||
func testFetchPersonIDs() {
|
||||
let mock = NetworkMock(json: ["results": [fakePerson1, fakePerson2]])
|
||||
wsDependencies.register(tag: WebService.PersonWS.tag, instance: mock as NetworkLayer)
|
||||
wsDependencies.register(tag: WebService.PersonWS.tag, .Singleton) { mock as NetworkLayer }
|
||||
|
||||
let provider = SWAPIPersonProvider()
|
||||
provider.fetchIDs { personIDs in
|
||||
@@ -38,7 +38,7 @@ class SWAPIPersonProviderTests: XCTestCase {
|
||||
func testFetchOnePerson() {
|
||||
|
||||
let mock = NetworkMock(json: fakePerson1)
|
||||
wsDependencies.register(tag: WebService.PersonWS.tag, instance: mock as NetworkLayer)
|
||||
wsDependencies.register(tag: WebService.PersonWS.tag, .Singleton) { mock as NetworkLayer }
|
||||
|
||||
let provider = SWAPIPersonProvider()
|
||||
provider.fetch(1) { person in
|
||||
@@ -58,7 +58,7 @@ class SWAPIPersonProviderTests: XCTestCase {
|
||||
func testFetchInvalidPerson() {
|
||||
let json = ["error":"whoops"]
|
||||
let mock = NetworkMock(json: json)
|
||||
wsDependencies.register(tag: WebService.PersonWS.tag, instance: mock as NetworkLayer)
|
||||
wsDependencies.register(tag: WebService.PersonWS.tag, .Singleton) { mock as NetworkLayer }
|
||||
|
||||
let provider = SWAPIPersonProvider()
|
||||
provider.fetch(12) { person in
|
||||
|
||||
@@ -23,7 +23,7 @@ class SWAPIStarshipProviderTests: XCTestCase {
|
||||
|
||||
func testFetchStarshipIDs() {
|
||||
let mock = NetworkMock(json: ["results": [fakeShip1, fakeShip2]])
|
||||
wsDependencies.register(tag: WebService.StarshipWS.tag, instance: mock as NetworkLayer)
|
||||
wsDependencies.register(tag: WebService.StarshipWS.tag, .Singleton) { mock as NetworkLayer }
|
||||
|
||||
let provider = SWAPIStarshipProvider()
|
||||
provider.fetchIDs { shipIDs in
|
||||
@@ -38,7 +38,7 @@ class SWAPIStarshipProviderTests: XCTestCase {
|
||||
func testFetchOneStarship() {
|
||||
|
||||
let mock = NetworkMock(json: fakeShip1)
|
||||
wsDependencies.register(tag: WebService.StarshipWS.tag, instance: mock as NetworkLayer)
|
||||
wsDependencies.register(tag: WebService.StarshipWS.tag, .Singleton) { mock as NetworkLayer }
|
||||
|
||||
let provider = SWAPIStarshipProvider()
|
||||
provider.fetch(1) { starship in
|
||||
@@ -57,7 +57,7 @@ class SWAPIStarshipProviderTests: XCTestCase {
|
||||
func testFetchInvalidStarship() {
|
||||
let json = ["error":"whoops"]
|
||||
let mock = NetworkMock(json: json)
|
||||
wsDependencies.register(tag: WebService.StarshipWS.tag, instance: mock as NetworkLayer)
|
||||
wsDependencies.register(tag: WebService.StarshipWS.tag, .Singleton) { mock as NetworkLayer }
|
||||
|
||||
let provider = SWAPIStarshipProvider()
|
||||
provider.fetch(12) { starship in
|
||||
|
||||
Reference in New Issue
Block a user