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
58 changes: 29 additions & 29 deletions Sources/SCInject/Container.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,27 @@ public final class DefaultContainer: Container {
// MARK: - Registry

public func register<T>(_ type: T.Type, closure: @escaping (Resolver) -> T) {
register(type: type, id: nil, scope: nil, closure: closure)
register(type: type, name: nil, scope: nil, closure: closure)
}

public func register<T>(_ type: T.Type, _ scope: Scope, closure: @escaping (Resolver) -> T) {
register(type: type, id: nil, scope: scope, closure: closure)
register(type: type, name: nil, scope: scope, closure: closure)
}

public func register<T>(_ type: T.Type, id: String, closure: @escaping (Resolver) -> T) {
register(type: type, id: .init(rawValue: id), scope: nil, closure: closure)
public func register<T>(_ type: T.Type, name: String, closure: @escaping (Resolver) -> T) {
register(type: type, name: .init(rawValue: name), scope: nil, closure: closure)
}

public func register<T>(_ type: T.Type, id: String, _ scope: Scope, closure: @escaping (Resolver) -> T) {
register(type: type, id: .init(rawValue: id), scope: scope, closure: closure)
public func register<T>(_ type: T.Type, name: String, _ scope: Scope, closure: @escaping (Resolver) -> T) {
register(type: type, name: .init(rawValue: name), scope: scope, closure: closure)
}

public func register<T>(_ type: T.Type, id: Identifier, closure: @escaping (Resolver) -> T) {
register(type: type, id: id, scope: nil, closure: closure)
public func register<T>(_ type: T.Type, name: RegisterName, closure: @escaping (Resolver) -> T) {
register(type: type, name: name, scope: nil, closure: closure)
}

public func register<T>(_ type: T.Type, id: Identifier, _ scope: Scope, closure: @escaping (Resolver) -> T) {
register(type: type, id: id, scope: scope, closure: closure)
public func register<T>(_ type: T.Type, name: RegisterName, _ scope: Scope, closure: @escaping (Resolver) -> T) {
register(type: type, name: name, scope: scope, closure: closure)
}

// MARK: - Resolver
Expand All @@ -64,13 +64,13 @@ public final class DefaultContainer: Container {
return instance
}

public func resolve<T>(_ type: T.Type, id: String) -> T {
resolve(type, id: .init(rawValue: id))
public func resolve<T>(_ type: T.Type, name: String) -> T {
resolve(type, name: .init(rawValue: name))
}

public func resolve<T>(_ type: T.Type, id: Identifier) -> T {
guard let instance = tryResolve(type, id: id) else {
let message = errorMessage("Failed to resolve given type -- TYPE=\(type) ID=\(id.rawValue)")
public func resolve<T>(_ type: T.Type, name: RegisterName) -> T {
guard let instance = tryResolve(type, name: name) else {
let message = errorMessage("Failed to resolve given type -- TYPE=\(type) NAME=\(name.rawValue)")
fatalError(message)
}
return instance
Expand All @@ -79,42 +79,42 @@ public final class DefaultContainer: Container {
// MARK: - Public

public func tryResolve<T>(_ type: T.Type) -> T? {
tryResolve(type: type, id: nil, container: self)
tryResolve(type: type, name: nil, container: self)
}

public func tryResolve<T>(_ type: T.Type, id: String) -> T? {
tryResolve(type: type, id: .init(rawValue: id), container: self)
public func tryResolve<T>(_ type: T.Type, name: String) -> T? {
tryResolve(type: type, name: .init(rawValue: name), container: self)
}

public func tryResolve<T>(_ type: T.Type, id: Identifier) -> T? {
tryResolve(type: type, id: id, container: self)
public func tryResolve<T>(_ type: T.Type, name: RegisterName) -> T? {
tryResolve(type: type, name: name, container: self)
}

// MARK: - Private

private func register<T>(
type: T.Type,
id: Identifier?,
name: RegisterName?,
scope: Scope?,
closure: @escaping (Resolver) -> T
) {
lock.lock(); defer { lock.unlock() }
let identifier = identifier(of: type, id: id)
let identifier = identifier(of: type, name: name)
if resolvers[identifier] != nil {
let message =
errorMessage("Given type is already registered -- TYPE=\(type) ID=\(id?.rawValue ?? "nil")")
errorMessage("Given type is already registered -- TYPE=\(type) NAME=\(name?.rawValue ?? "nil")")
fatalError(message)
}
resolvers[identifier] = makeResolver(scope ?? defaultScope, closure: closure)
}

private func tryResolve<T>(type: T.Type, id: Identifier? = nil, container: Container) -> T? {
private func tryResolve<T>(type: T.Type, name: RegisterName? = nil, container: Container) -> T? {
lock.lock(); defer { lock.unlock() }
if let resolver = resolvers[identifier(of: type, id: id)] {
if let resolver = resolvers[identifier(of: type, name: name)] {
return resolver.resolve(with: container) as? T
}
if let parent {
return parent.tryResolve(type: type, id: id, container: container)
return parent.tryResolve(type: type, name: name, container: container)
}
return nil
}
Expand All @@ -128,16 +128,16 @@ public final class DefaultContainer: Container {
}
}

private func identifier(of type: (some Any).Type, id: Identifier?) -> ResolverIdentifier {
private func identifier(of type: (some Any).Type, name: RegisterName?) -> ResolverIdentifier {
ResolverIdentifier(
id: id,
name: name,
typeIdentifier: ObjectIdentifier(type),
description: String(describing: type)
)
}

private struct ResolverIdentifier: Hashable {
let id: Identifier?
let name: RegisterName?
let typeIdentifier: ObjectIdentifier
let description: String
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@

import Foundation

public struct Identifier: RawRepresentable, CustomStringConvertible, Hashable {
public struct RegisterName: RawRepresentable, CustomStringConvertible, Hashable {
public let rawValue: String

public init(rawValue string: String) {
rawValue = string
}

public var description: String {
"SCInject.Identifier(\(rawValue))"
"SCInject.RegisterName(\(rawValue))"
}
}
8 changes: 4 additions & 4 deletions Sources/SCInject/Registry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public protocol Registry {
func register<T>(_ type: T.Type, closure: @escaping (Resolver) -> T)
func register<T>(_ type: T.Type, _ scope: Scope, closure: @escaping (Resolver) -> T)

func register<T>(_ type: T.Type, id: String, closure: @escaping (Resolver) -> T)
func register<T>(_ type: T.Type, id: String, _ scope: Scope, closure: @escaping (Resolver) -> T)
func register<T>(_ type: T.Type, name: String, closure: @escaping (Resolver) -> T)
func register<T>(_ type: T.Type, name: String, _ scope: Scope, closure: @escaping (Resolver) -> T)

func register<T>(_ type: T.Type, id: Identifier, closure: @escaping (Resolver) -> T)
func register<T>(_ type: T.Type, id: Identifier, _ scope: Scope, closure: @escaping (Resolver) -> T)
func register<T>(_ type: T.Type, name: RegisterName, closure: @escaping (Resolver) -> T)
func register<T>(_ type: T.Type, name: RegisterName, _ scope: Scope, closure: @escaping (Resolver) -> T)
}
4 changes: 2 additions & 2 deletions Sources/SCInject/Resolver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ import Foundation

public protocol Resolver: AnyObject {
func resolve<T>(_ type: T.Type) -> T
func resolve<T>(_ type: T.Type, id: String) -> T
func resolve<T>(_ type: T.Type, id: Identifier) -> T
func resolve<T>(_ type: T.Type, name: String) -> T
func resolve<T>(_ type: T.Type, name: RegisterName) -> T
}
38 changes: 19 additions & 19 deletions Tests/SCInject/ContainerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ final class ContainerTests: XCTestCase {
// When
let class1 = container.tryResolve(TestClass1.self)
let class2 = container.tryResolve(TestClass2.self)
let class1_id = container.tryResolve(TestClass1.self, id: "Test")
let class2_id = container.tryResolve(TestClass2.self, id: "Test")
let class1_id_second = container.tryResolve(TestClass1.self, id: .init(rawValue: "Test"))
let class2_id_second = container.tryResolve(TestClass2.self, id: .init(rawValue: "Test"))
let class1_name = container.tryResolve(TestClass1.self, name: "Test")
let class2_name = container.tryResolve(TestClass2.self, name: "Test")
let class1_name_second = container.tryResolve(TestClass1.self, name: .init(rawValue: "Test"))
let class2_name_second = container.tryResolve(TestClass2.self, name: .init(rawValue: "Test"))
let class1_second = container.tryResolve(TestClass1.self)
let class2_second = container.tryResolve(TestClass2.self)

Expand All @@ -45,43 +45,43 @@ final class ContainerTests: XCTestCase {
XCTAssertNotNil(class2)
XCTAssertNotNil(class1_second)
XCTAssertNotNil(class2_second)
XCTAssertNil(class1_id)
XCTAssertNil(class2_id)
XCTAssertNil(class1_id_second)
XCTAssertNil(class2_id_second)
XCTAssertNil(class1_name)
XCTAssertNil(class2_name)
XCTAssertNil(class1_name_second)
XCTAssertNil(class2_name_second)
XCTAssertTrue(class1 !== class1_second)
XCTAssertTrue(class2 !== class2_second)
XCTAssertTrue(class2?.value !== class1)
}

func testRegister_transientClassWithId() {
let second: Identifier = .init(rawValue: "second")
func testRegister_transientClassWithName() {
let second: RegisterName = .init(rawValue: "second")
let container = DefaultContainer()
container.register(TestClass1.self) { _ in
TestClass1(value: "TestClass1_Instance")
}
container.register(TestClass1.self, id: second) { _ in
container.register(TestClass1.self, name: second) { _ in
TestClass1(value: "TestClass1_Second_Instance")
}
container.register(TestClass2.self) { r in
TestClass2(value: r.resolve(TestClass1.self, id: second))
TestClass2(value: r.resolve(TestClass1.self, name: second))
}

// When
let class1 = container.tryResolve(TestClass1.self)
let class2 = container.tryResolve(TestClass2.self)
let class1_id = container.tryResolve(TestClass1.self, id: second)
let class2_id = container.tryResolve(TestClass2.self, id: second)
let class1_name = container.tryResolve(TestClass1.self, name: second)
let class2_name = container.tryResolve(TestClass2.self, name: second)

// Then
XCTAssertNotNil(class1)
XCTAssertNotNil(class2)
XCTAssertNotNil(class1_id)
XCTAssertNil(class2_id)
XCTAssertEqual(class1_id?.rawValue, "TestClass1_Second_Instance")
XCTAssertNotNil(class1_name)
XCTAssertNil(class2_name)
XCTAssertEqual(class1_name?.rawValue, "TestClass1_Second_Instance")
XCTAssertEqual(class2?.value.rawValue, "TestClass1_Second_Instance")
XCTAssertTrue(class1 !== class1_id)
XCTAssertTrue(class2?.value !== class1_id)
XCTAssertTrue(class1 !== class1_name)
XCTAssertTrue(class2?.value !== class1_name)
}
}

Expand Down