Skip to content

Commit

Permalink
minor wrappers refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
ilyapuchka committed Nov 23, 2015
1 parent 706e16a commit 1377a9b
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 35 deletions.
60 changes: 35 additions & 25 deletions Dip/Dip/AutoInjection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ class ClientImp: Client {
*/
public final class Injected<T>: _Injected {

static var tag: DependencyContainer.Tag {
return .String("\(Injected<T>.self)")
}

var _value: Any?

public init() {}

public var value: T? {
get {
return _value as? T
Expand All @@ -58,7 +60,9 @@ public final class Injected<T>: _Injected {
_value = newValue
}
}


public init() {}

}

/**
Expand Down Expand Up @@ -97,10 +101,12 @@ public final class InjectedWeak<T>: _InjectedWeak {
//so we just rely on user reading documentation and passing AnyObject in runtime
//also we will throw fatal error if type can not be casted to AnyObject during resolution

static var tag: DependencyContainer.Tag {
return .String("\(InjectedWeak<T>.self)")
}

weak var _value: AnyObject?

public init() {}

public var value: T? {
get {
return _value as? T
Expand All @@ -109,7 +115,9 @@ public final class InjectedWeak<T>: _InjectedWeak {
_value = newValue as? AnyObject
}
}


public init() {}

}

extension DependencyContainer {
Expand Down Expand Up @@ -140,16 +148,8 @@ extension DependencyContainer {
*/
public func resolveDependencies(instance: Any) {
for child in Mirror(reflecting: instance).children
where child.value is _Injected || child.value is _InjectedWeak {

let tag = Tag.String("\(child.value.dynamicType)")
if let value = child.value as? _Injected {
value._value = resolve(tag: tag) as Any
}
else if let weakValue = child.value as? _InjectedWeak {
weakValue._value = resolve(tag: tag) as AnyObject
}
for child in Mirror(reflecting: instance).children {
(child.value as? _AutoInjected)?.resolve(self)
}
}

Expand All @@ -162,11 +162,11 @@ extension DependencyContainer {
typealias InjectedWeakFactory = ()->AnyObject

static func injectedKey<T>(type: T.Type) -> DefinitionKey {
return DefinitionKey(protocolType: Any.self, factoryType: InjectedFactory.self, associatedTag: Tag.String(injectedTag(type)))
return DefinitionKey(protocolType: Any.self, factoryType: InjectedFactory.self, associatedTag: Injected<T>.tag)
}

static func injectedWeakKey<T>(type: T.Type) -> DefinitionKey {
return DefinitionKey(protocolType: AnyObject.self, factoryType: InjectedWeakFactory.self, associatedTag: Tag.String(injectedWeakTag(type)))
return DefinitionKey(protocolType: AnyObject.self, factoryType: InjectedWeakFactory.self, associatedTag: InjectedWeak<T>.tag)
}

func registerInjected<T, F>(definition: DefinitionOf<T, F>) {
Expand All @@ -191,19 +191,29 @@ extension DependencyContainer {

}

func injectedTag<T>(type: T.Type) -> String {
return "\(Injected<T>().dynamicType)"
protocol _AutoInjected {
func resolve(container: DependencyContainer)
static var tag: DependencyContainer.Tag { get }
}

func injectedWeakTag<T>(type: T.Type) -> String {
return "\(InjectedWeak<T>().dynamicType)"
protocol _Injected: class, _AutoInjected {
var _value: Any? { get set }
}

protocol _Injected: class {
var _value: Any? { get set }
extension _Injected {
func resolve(container: DependencyContainer) {
self._value = container.resolve(tag: self.dynamicType.tag) as Any
}
}

protocol _InjectedWeak: class {
protocol _InjectedWeak: class, _AutoInjected {
weak var _value: AnyObject? { get set }
}

extension _InjectedWeak {
func resolve(container: DependencyContainer) {
self._value = container.resolve(tag: self.dynamicType.tag) as AnyObject
}
}


4 changes: 2 additions & 2 deletions Dip/Dip/Definition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,14 @@ public final class DefinitionOf<T, F>: Definition {
self.tag = tag

if let factory = factory as? ()->T where tag == nil {
injectedDefinition = DefinitionOf<Any, ()->Any>(factory: { factory() }, scope: scope, tag: DependencyContainer.Tag.String(injectedTag(T.self)))
injectedDefinition = DefinitionOf<Any, ()->Any>(factory: { factory() }, scope: scope, tag: Injected<T>.tag)

injectedWeakDefinition = DefinitionOf<AnyObject, ()->AnyObject>(factory: {
guard let result = factory() as? AnyObject else {
fatalError("\(T.self) can not be casted to AnyObject. InjectedWeak wrapper should be used to wrap only classes.")
}
return result
}, scope: scope, tag: DependencyContainer.Tag.String(injectedWeakTag(T.self)))
}, scope: scope, tag: InjectedWeak<T>.tag)
}

}
Expand Down
6 changes: 4 additions & 2 deletions Dip/DipTests/AutoInjectionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,13 @@ class AutoInjectionTests: XCTestCase {

override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.

container.reset()
AutoInjectionTests.serverDeallocated = false
AutoInjectionTests.clientDeallocated = false

container.register(.ObjectGraph) { ServerImp() as Server }
container.register(.ObjectGraph) { ClientImp() as Client }

}

func testThatItResolvesInjectedDependencies() {
Expand All @@ -100,15 +99,18 @@ class AutoInjectionTests: XCTestCase {
func testThatItResolvesAutoInjectedSingletons() {
container.reset()

//given
container.register(.Singleton) { ServerImp() as Server }
container.register(.Singleton) { ClientImp() as Client }

//when
let sharedClient = container.resolve() as Client
let sharedServer = container.resolve() as Server

let client = container.resolve() as Client
let server = client.server

//then
XCTAssertTrue(client as! ClientImp === sharedClient as! ClientImp)
XCTAssertTrue(client as! ClientImp === server?.client as! ClientImp)
XCTAssertTrue(server as! ServerImp === sharedServer as! ServerImp)
Expand Down
6 changes: 0 additions & 6 deletions Dip/DipTests/ComponentScopeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,9 @@ class ComponentScopeTests: XCTestCase {

override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
container.reset()
}

override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}

func testThatPrototypeIsDefaultScope() {
let def = container.register { ServiceImp1() as Service }
XCTAssertEqual(def.scope, ComponentScope.Prototype)
Expand Down

0 comments on commit 1377a9b

Please sign in to comment.