Compare commits

...

10 Commits

Author SHA1 Message Date
Olivier Halligon feb5064b93 Merge branch 'release/3.1.0' 2015-11-30 12:30:20 +01:00
Ilya Puchka 184e1f4543 CHANGELOG minor fix 2015-11-30 10:55:12 +01:00
Olivier Halligon 8be1139114 CHANGELOG re-org 2015-11-29 23:34:29 +01:00
Ilya Puchka afc8e49b18 bumped project version 2015-11-27 12:52:21 +01:00
Ilya Puchka 333fa96b62 added name for first runtime argument in resolve 2015-11-27 12:47:41 +01:00
Ilya Puchka d611ea240e added scope argument 2015-11-27 12:38:03 +01:00
Ilya Puchka ee16baacfc Merge branch 'master' into release/3.1.0 2015-11-26 23:37:02 +01:00
Ilya Puchka b4221e25a1 Merge pull request #17 from AliSoftware/hotfix/migration-note
Added note on migration from 2.0.0 to 3.0.0
2015-11-26 17:38:04 +01:00
Ilya Puchka 0edd3747e8 added note on migration from 2.0.0 to 3.0.0 2015-11-26 17:21:16 +01:00
Olivier Halligon 2708f7e434 Merge branch 'release/3.0.0' into develop 2015-11-22 14:32:49 +01:00
12 changed files with 169 additions and 83 deletions
+32
View File
@@ -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
View File
@@ -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
+4 -4
View File
@@ -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
View File
@@ -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)
}
+54 -18
View File
@@ -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) }
}
+1 -1
View File
@@ -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
+18 -18
View File
@@ -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
+37 -23
View File
@@ -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