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
2 changes: 2 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
excluded:
- DIDemoApp
- Package.swift

line_length: 140
28 changes: 27 additions & 1 deletion Sources/SwinjectLight/Container.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import Foundation

#if canImport(Darwin)
@MainActor
#endif
public protocol Resolver: AnyObject {
func resolve<Service>(_ type: Service.Type) -> Service
}

public final class Container: @unchecked Sendable {
public final class Container {
private var storage: [String: Any] = [:]

public init() { }
Expand All @@ -13,8 +16,19 @@ public final class Container: @unchecked Sendable {
let key = "\(type)"
storage[key] = factory
}

public func register<Service, Parameters>(_ type: Service.Type,
parametersType: Parameters.Type,
factory: @escaping (Resolver, Parameters) -> Service) {
let key = "\(type)"
storage[key] = factory
}
}

#if !canImport(Darwin)
extension Container: @unchecked Sendable { }
#endif

extension Container: Resolver {
public func resolve<Service>(_ type: Service.Type) -> Service {
let key = "\(type)"
Expand All @@ -27,4 +41,16 @@ extension Container: Resolver {
let service = typedFactory?(self)
return service!
}

public func resolve<Service, Parameters>(_ type: Service.Type, parameters: Parameters) -> Service {
let key = "\(type)"
guard let factory = storage[key] else {
fatalError("Dependency \(key) has not been registered")
}
guard let typedFactory = factory as? (((Resolver, Parameters) -> Service)?) else {
fatalError("Dependency \(key) did not provide factory closure")
}
let service = typedFactory?(self, parameters)
return service!
}
}
31 changes: 31 additions & 0 deletions Tests/SwinjectLightTests/SwinjectLightTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,25 @@ import XCTest
@testable import SwinjectLight

private protocol MockDependency: AnyObject { }
private protocol MockParametersDependency: AnyObject { }
private class MockClass: MockDependency { }
private class MockClassWithParameters: MockParametersDependency {
struct Parameters: Equatable {
let foo: String
}

let parameters: Parameters
let dependency: MockDependency

init(dependency: MockDependency, parameters: Parameters) {
self.dependency = dependency
self.parameters = parameters
}
}

#if canImport(Darwin)
@MainActor
#endif
final class SwinjectLightTests: XCTestCase {
func testRegisterAndResolve() {
let container = Container()
Expand All @@ -26,4 +43,18 @@ final class SwinjectLightTests: XCTestCase {
XCTAssertTrue(resolvedDependency is MockClass)
XCTAssertTrue(localVariable === resolvedDependency)
}

func testRegisterAndResolveWithParameters() {
let container = Container()
let parameters = MockClassWithParameters.Parameters(foo: "foo")
container.register(MockDependency.self) { _ in MockClass() }
container.register(MockParametersDependency.self, parametersType: MockClassWithParameters.Parameters.self) { resolver, parameters in
MockClassWithParameters(dependency: resolver.resolve(MockDependency.self), parameters: parameters)
}

let resolvedDependency = container.resolve(MockParametersDependency.self, parameters: parameters)
XCTAssertTrue(resolvedDependency is MockClassWithParameters)
XCTAssertTrue((resolvedDependency as? MockClassWithParameters)?.dependency is MockDependency)
XCTAssertEqual((resolvedDependency as? MockClassWithParameters)?.parameters, parameters)
}
}
Loading