Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Dip/Dip/Definition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ public final class DefinitionOf<T, F>: Definition {

var definition = container.register { ServiceImp() as Service }
definition.resolveDependencies { container, service in
service.delegate = container.resolve() as Client
service.delegate = try container.resolve() as Client
}
```

*/
public func resolveDependencies(block: (DependencyContainer, T) -> ()) -> DefinitionOf<T, F> {
public func resolveDependencies(block: (DependencyContainer, T) throws -> ()) -> DefinitionOf<T, F> {
guard resolveDependenciesBlock == nil else {
fatalError("You can not change resolveDependencies block after it was set.")
}
Expand All @@ -96,7 +96,7 @@ public final class DefinitionOf<T, F>: Definition {

let factory: F
var scope: ComponentScope
var resolveDependenciesBlock: ((DependencyContainer, T) -> ())?
var resolveDependenciesBlock: ((DependencyContainer, T) throws -> ())?

init(factory: F, scope: ComponentScope) {
self.factory = factory
Expand Down
26 changes: 14 additions & 12 deletions Dip/Dip/Dip.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public final class DependencyContainer {
container.register { ClientImp(service: try! container.resolve() as Service) as Client }
```
*/
public func register<T>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: ()->T) -> DefinitionOf<T, ()->T> {
public func register<T>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: () throws -> T) -> DefinitionOf<T, () throws ->T> {
return registerFactory(tag: tag, scope: scope, factory: factory)
}

Expand Down Expand Up @@ -163,7 +163,7 @@ public final class DependencyContainer {

*/
public func resolve<T>(tag tag: Tag? = nil) throws -> T {
return try resolve(tag: tag) { (factory: ()->T) in factory() }
return try resolve(tag: tag) { (factory: () throws -> T) in try factory() }
}

/**
Expand All @@ -186,28 +186,30 @@ public final class DependencyContainer {
Though before you do that you should probably review your design and try to reduce the number of dependencies.

*/
public func resolve<T, F>(tag tag: Tag? = nil, builder: F->T) throws -> T {
public func resolve<T, F>(tag tag: Tag? = nil, builder: F throws -> T) throws -> T {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if the outer throws should be throws or rethrows?

http://robnapier.net/re-throws

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here rethrows will not compile cause this method throws error itself.

let key = DefinitionKey(protocolType: T.self, factoryType: F.self, associatedTag: tag)
let nilTagKey = tag.map { _ in DefinitionKey(protocolType: T.self, factoryType: F.self, associatedTag: nil) }

guard let definition = (self.definitions[key] ?? self.definitions[nilTagKey]) as? DefinitionOf<T, F> else {
throw DipError.DefinitionNotFound(key)
let error = DipError.DefinitionNotFound(key)
print("\(error)")
throw error
}

let usingKey: DefinitionKey? = definition.scope == .ObjectGraph ? key : nil
return _resolve(tag, key: usingKey, definition: definition, builder: builder)
return try _resolve(tag, key: usingKey, definition: definition, builder: builder)
}

/// Actually resolve dependency
private func _resolve<T, F>(tag: Tag? = nil, key: DefinitionKey?, definition: DefinitionOf<T, F>, builder: F->T) -> T {
private func _resolve<T, F>(tag: Tag? = nil, key: DefinitionKey?, definition: DefinitionOf<T, F>, builder: F throws -> T) rethrows -> T {

return resolvedInstances.resolve {
return try resolvedInstances.resolve {

if let previouslyResolved: T = resolvedInstances.previouslyResolved(key, definition: definition) {
return previouslyResolved
}
else {
let resolvedInstance = builder(definition.factory)
let resolvedInstance = try builder(definition.factory)

//when builder calls factory it will in turn resolve sub-dependencies (if there are any)
//when it returns instance that we try to resolve here can be already resolved
Expand All @@ -218,7 +220,7 @@ public final class DependencyContainer {

resolvedInstances.storeResolvedInstance(resolvedInstance, forKey: key)
definition.resolvedInstance = resolvedInstance
definition.resolveDependenciesBlock?(self, resolvedInstance)
try definition.resolveDependenciesBlock?(self, resolvedInstance)

return resolvedInstance
}
Expand Down Expand Up @@ -246,9 +248,9 @@ public final class DependencyContainer {

private var depth: Int = 0

func resolve<T>(@noescape block: ()->T) -> T {
func resolve<T>(@noescape block: () throws ->T) rethrows -> T {
depth++
let resolved = block()
let resolved = try block()
depth--
if depth == 0 {
resolvedInstances.removeAll()
Expand Down Expand Up @@ -307,7 +309,7 @@ public enum DipError: ErrorType, CustomStringConvertible {
public var description: String {
switch self {
case let .DefinitionNotFound(key):
return "No definition registered for \(key). Check the tag, type you try to resolve, number, order and types of runtime arguments passed to `resolve()`."
return "Failed to resolve type \(key.protocolType) - no definition registered for \(key).\nCheck the tag, type you try to resolve, number, order and types of runtime arguments passed to `resolve()` and match them with registered factories for type \(key.protocolType)."
}
}
}
Expand Down
36 changes: 18 additions & 18 deletions Dip/Dip/RuntimeArguments.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ extension DependencyContainer {

- seealso: `registerFactory(tag:scope:factory:)`
*/
public func register<T, Arg1>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1) -> T) -> DefinitionOf<T, (Arg1) -> T> {
return registerFactory(tag: tag, scope: scope, factory: factory) as DefinitionOf<T, (Arg1) -> T>
public func register<T, Arg1>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1) throws -> T) -> DefinitionOf<T, (Arg1) throws -> T> {
return registerFactory(tag: tag, scope: scope, factory: factory)
}

/**
Expand All @@ -55,63 +55,63 @@ extension DependencyContainer {
- seealso: `resolve(tag:builder:)`
*/
public func resolve<T, Arg1>(tag tag: Tag? = nil, withArguments arg1: Arg1) throws -> T {
return try resolve(tag: tag) { (factory: (Arg1) -> T) in factory(arg1) }
return try resolve(tag: tag) { (factory: (Arg1) throws -> T) in try factory(arg1) }
}

// MARK: 2 Runtime Arguments

/// - seealso: `register(:factory:scope:)`
public func register<T, Arg1, Arg2>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2) -> T) -> DefinitionOf<T, (Arg1, Arg2) -> T> {
return registerFactory(tag: tag, scope: scope, factory: factory) as DefinitionOf<T, (Arg1, Arg2) -> T>
public func register<T, Arg1, Arg2>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2) throws -> T) -> DefinitionOf<T, (Arg1, Arg2) throws -> T> {
return registerFactory(tag: tag, scope: scope, factory: factory)
}

/// - seealso: `resolve(tag:_:)`
public func resolve<T, Arg1, Arg2>(tag tag: Tag? = nil, withArguments arg1: Arg1, _ arg2: Arg2) throws -> T {
return try resolve(tag: tag) { (factory: (Arg1, Arg2) -> T) in factory(arg1, arg2) }
return try resolve(tag: tag) { (factory: (Arg1, Arg2) throws -> T) in try factory(arg1, arg2) }
}

// MARK: 3 Runtime Arguments

public func register<T, Arg1, Arg2, Arg3>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3) -> T) -> DefinitionOf<T, (Arg1, Arg2, Arg3) -> T> {
return registerFactory(tag: tag, scope: scope, factory: factory) as DefinitionOf<T, (Arg1, Arg2, Arg3) -> T>
public func register<T, Arg1, Arg2, Arg3>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3) throws -> T) -> DefinitionOf<T, (Arg1, Arg2, Arg3) throws -> T> {
return registerFactory(tag: tag, scope: scope, factory: factory)
}

/// - seealso: `resolve(tag:withArguments:)`
public func resolve<T, Arg1, Arg2, Arg3>(tag tag: Tag? = nil, withArguments arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3) throws -> T {
return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3) -> T) in factory(arg1, arg2, arg3) }
return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3) throws -> T) in try factory(arg1, arg2, arg3) }
}

// MARK: 4 Runtime Arguments

public func register<T, Arg1, Arg2, Arg3, Arg4>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3, Arg4) -> T) -> DefinitionOf<T, (Arg1, Arg2, Arg3, Arg4) -> T> {
return registerFactory(tag: tag, scope: scope, factory: factory) as DefinitionOf<T, (Arg1, Arg2, Arg3, Arg4) -> T>
public func register<T, Arg1, Arg2, Arg3, Arg4>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3, Arg4) throws -> T) -> DefinitionOf<T, (Arg1, Arg2, Arg3, Arg4) throws -> T> {
return registerFactory(tag: tag, scope: scope, factory: factory)
}

/// - 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) throws -> T {
return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4) -> T) in factory(arg1, arg2, arg3, arg4) }
return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4) throws -> T) in try factory(arg1, arg2, arg3, arg4) }
}

// MARK: 5 Runtime Arguments

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, (Arg1, Arg2, Arg3, Arg4, Arg5) -> T> {
return registerFactory(tag: tag, scope: scope, factory: factory) as DefinitionOf<T, (Arg1, Arg2, Arg3, Arg4, Arg5) -> T>
public func register<T, Arg1, Arg2, Arg3, Arg4, Arg5>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3, Arg4, Arg5) throws -> T) -> DefinitionOf<T, (Arg1, Arg2, Arg3, Arg4, Arg5) throws -> T> {
return registerFactory(tag: tag, scope: scope, factory: factory)
}

/// - 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) throws -> T {
return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4, Arg5) -> T) in factory(arg1, arg2, arg3, arg4, arg5) }
return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4, Arg5) throws -> T) in try factory(arg1, arg2, arg3, arg4, arg5) }
}

// MARK: 6 Runtime Arguments

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, (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) -> T> {
return registerFactory(tag: tag, scope: scope, factory: factory) as DefinitionOf<T, (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) -> 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) throws -> T) -> DefinitionOf<T, (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) throws -> T> {
return registerFactory(tag: tag, scope: scope, factory: factory)
}

/// - 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) throws -> T {
return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) -> T) in factory(arg1, arg2, arg3, arg4, arg5, arg6) }
return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) throws -> T) in try factory(arg1, arg2, arg3, arg4, arg5, arg6) }
}

}
10 changes: 5 additions & 5 deletions Dip/DipTests/ComponentScopeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,10 @@ class ComponentScopeTests: XCTestCase {

func testThatItReusesInstanceInObjectGraphScopeDuringResolve() {
//given
container.register(.ObjectGraph) { Client(server: try! self.container.resolve()) as Client }
container.register(.ObjectGraph) { Client(server: try self.container.resolve()) as Client }

container.register(.ObjectGraph) { Server() as Server }.resolveDependencies { container, server in
server.client = try! container.resolve() as Client
server.client = try container.resolve() as Client
}

//when
Expand All @@ -106,9 +106,9 @@ class ComponentScopeTests: XCTestCase {

func testThatItDoesNotReuseInstanceInObjectGraphScopeInNextResolve() {
//given
container.register(.ObjectGraph) { Client(server: try! self.container.resolve()) as Client }
container.register(.ObjectGraph) { Client(server: try self.container.resolve()) as Client }
container.register(.ObjectGraph) { Server() as Server }.resolveDependencies { container, server in
server.client = try! container.resolve() as Client
server.client = try container.resolve() as Client
}

//when
Expand All @@ -127,7 +127,7 @@ class ComponentScopeTests: XCTestCase {
//given
var service2: Service?
container.register(.ObjectGraph) { ServiceImp1() as Service }.resolveDependencies { (c, _) in
service2 = try! c.resolve(tag: "service") as Service
service2 = try c.resolve(tag: "service") as Service
}
container.register(tag: "service", .ObjectGraph) { ServiceImp2() as Service}

Expand Down
6 changes: 3 additions & 3 deletions Dip/DipTests/DipTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class DipTests: XCTestCase {
XCTFail("Unexpectedly resolved protocol")
}
catch DipError.DefinitionNotFound(let key) {
typealias F = ()->Service
typealias F = () throws -> Service
let expectedKey = DefinitionKey(protocolType: Service.self, factoryType: F.self, associatedTag: nil)
XCTAssertEqual(key, expectedKey)
}
Expand All @@ -141,7 +141,7 @@ class DipTests: XCTestCase {
XCTFail("Unexpectedly resolved protocol")
}
catch DipError.DefinitionNotFound(let key) {
typealias F = ()->Service
typealias F = () throws -> Service
let expectedKey = DefinitionKey(protocolType: Service.self, factoryType: F.self, associatedTag: "other tag")
XCTAssertEqual(key, expectedKey)
}
Expand All @@ -160,7 +160,7 @@ class DipTests: XCTestCase {
XCTFail("Unexpectedly resolved protocol")
}
catch DipError.DefinitionNotFound(let key) {
typealias F = (String)->Service
typealias F = (String) throws -> Service
let expectedKey = DefinitionKey(protocolType: Service.self, factoryType: F.self, associatedTag: nil)
XCTAssertEqual(key, expectedKey)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ Now you can register those classes in container:
*/

container.register(.ObjectGraph) {
Interactor(networkClient: try! container.resolve()) as NetworkClientDelegate
Interactor(networkClient: try container.resolve()) as NetworkClientDelegate
}

container.register(.ObjectGraph) { NetworkClientImp() as NetworkClient }
.resolveDependencies { (container, client) -> () in
client.delegate = try! container.resolve() as NetworkClientDelegate
client.delegate = try container.resolve() as NetworkClientDelegate
}

/*:
Expand Down Expand Up @@ -92,12 +92,12 @@ If we would have used `.Prototype` for one of the components it will lead to the
container.reset()

container.register(.Prototype) {
Interactor(networkClient: try! container.resolve()) as NetworkClientDelegate
Interactor(networkClient: try container.resolve()) as NetworkClientDelegate
}

container.register(.ObjectGraph) { NetworkClientImp() as NetworkClient }
.resolveDependencies { (container, client) -> () in
client.delegate = try! container.resolve() as NetworkClientDelegate
client.delegate = try container.resolve() as NetworkClientDelegate
}

let invalidInteractor = try! container.resolve() as NetworkClientDelegate
Expand Down
2 changes: 1 addition & 1 deletion DipPlayground.playground/contents.xcplayground
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='6.0' target-platform='ios' display-mode='raw'>
<playground version='6.0' target-platform='ios' display-mode='rendered'>
<pages>
<page name='What is Dip?'/>
<page name='Creating container'/>
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,12 @@ _Dip_ supports circular dependencies. To resolve them use `ObjectGraph` scope an

```swift
container.register(.ObjectGraph) {
ClientImp(server: try! container.resolve() as Server) as Client
ClientImp(server: try container.resolve() as Server) as Client
}

container.register(.ObjectGraph) { ServerImp() as Server }
.resolveDependencies { container, server in
server.client = try! container.resolve() as Client
server.client = try container.resolve() as Client
}
```
More infromation about circular dependencies you can find in a playground.
Expand Down