-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
213 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"object": { | ||
"pins": [ | ||
{ | ||
"package": "Swinject", | ||
"repositoryURL": "https://github.com/Swinject/Swinject.git", | ||
"state": { | ||
"branch": null, | ||
"revision": "463cb2d659c8ae34899d18057ea5b1bb86fc3178", | ||
"version": "2.8.4" | ||
} | ||
} | ||
] | ||
}, | ||
"version": 1 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,33 @@ | ||
// swift-tools-version: 5.9 | ||
// swift-tools-version:5.0 | ||
// The swift-tools-version declares the minimum version of Swift required to build this package. | ||
|
||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "SwinjectExtension", | ||
products: [ | ||
// Products define the executables and libraries a package produces, making them visible to other packages. | ||
.library( | ||
name: "SwinjectExtension", | ||
targets: ["SwinjectExtension"]), | ||
name: "SwinjectExtension-Dynamic", | ||
type: .dynamic, | ||
targets: ["SwinjectExtension"] | ||
) | ||
], | ||
dependencies: [ | ||
.package(url: "https://github.com/Swinject/Swinject.git", from: "2.8.0") | ||
], | ||
targets: [ | ||
// Targets are the basic building blocks of a package, defining a module or a test suite. | ||
// Targets can depend on other targets in this package and products from dependencies. | ||
.target( | ||
name: "SwinjectExtension"), | ||
name: "SwinjectExtension", | ||
dependencies: [ | ||
.product(name: "Swinject") | ||
] | ||
), | ||
.testTarget( | ||
name: "SwinjectExtensionTests", | ||
dependencies: ["SwinjectExtension"]), | ||
dependencies: [ | ||
"SwinjectExtension", | ||
.product(name: "Swinject") | ||
] | ||
) | ||
] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import Foundation | ||
import Swinject | ||
|
||
/// A custom container wrapping `Assembler` and `Container`. | ||
public final class DIContainer { | ||
|
||
/// A singleton object. Assembler is initialized with baseline container. | ||
public static let shared: DIContainer = .init(assembler: .init()) | ||
|
||
/// An assembler used to resolve service. | ||
public var assembler: Assembler | ||
|
||
public var container: Container { | ||
self.assembler.resolver as! Container | ||
} | ||
|
||
public var resolver: Resolver { | ||
self.assembler.resolver | ||
} | ||
|
||
init(assembler: Assembler) { | ||
self.assembler = assembler | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import Foundation | ||
import Swinject | ||
|
||
extension Swinject.Resolver { | ||
|
||
/// Retrieves the instance with the specified service type. Infer the type if can be inferred. | ||
/// | ||
/// If not found service, occur fatalError. | ||
/// | ||
/// - Parameter serviceType: The service type to resolve. | ||
/// - Returns: The resolved service type instance. | ||
public func resolve<Service>(_ serviceType: Service.Type = Service.self) -> Service { | ||
guard let resolved = self.resolve(serviceType) else { | ||
resolveOrFatalError(Service.self) | ||
} | ||
|
||
return resolved | ||
} | ||
|
||
public func resolve<Service>(_ serviceType: Service.Type = Service.self, name: String) -> Service { | ||
guard let resolved = self.resolve(serviceType, name: name) else { | ||
resolveOrFatalError(Service.self) | ||
} | ||
|
||
return resolved | ||
} | ||
|
||
public func resolve<Service, Arg1>(_ serviceType: Service.Type = Service.self, argument: Arg1) -> Service { | ||
guard let resolved = self.resolve(serviceType, argument: argument) else { | ||
resolveOrFatalError(Service.self) | ||
} | ||
|
||
return resolved | ||
} | ||
|
||
public func resolve<Service, Arg1, Arg2>(_ serviceType: Service.Type = Service.self, arguments: Arg1, _ arg2: Arg2) -> Service { | ||
guard let resolved = self.resolve(serviceType, arguments: arguments, arg2) else { | ||
resolveOrFatalError(Service.self) | ||
} | ||
|
||
return resolved | ||
} | ||
|
||
public func resolve<Service, Arg1, Arg2, Arg3>(_ serviceType: Service.Type = Service.self, arguments: Arg1, _ arg2: Arg2, _ arg3: Arg3) -> Service { | ||
guard let resolved = self.resolve(serviceType, arguments: arguments, arg2, arg3) else { | ||
resolveOrFatalError(Service.self) | ||
} | ||
|
||
return resolved | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,12 @@ | ||
// The Swift Programming Language | ||
// https://docs.swift.org/swift-book | ||
// | ||
// SwinjectExtension.swift | ||
// | ||
// | ||
// Created by Jaewon Yun on 2023/11/17. | ||
// | ||
|
||
import Foundation | ||
|
||
func resolveOrFatalError<Service>(_ serviceType: Service.Type, file: StaticString = #file, line: UInt = #line) -> Never { | ||
fatalError("Failed to resolve for '\(serviceType.self)' type.", file: file, line: line) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,96 @@ | ||
import XCTest | ||
@testable import SwinjectExtension | ||
import XCTest | ||
|
||
final class SwinjectExtensionTests: XCTestCase { | ||
func testExample() throws { | ||
// XCTest Documentation | ||
// https://developer.apple.com/documentation/xctest | ||
|
||
// Defining Test Cases and Test Methods | ||
// https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods | ||
override func setUp() { | ||
super.setUp() | ||
|
||
DIContainer.shared.assembler = .init() | ||
} | ||
|
||
override func tearDown() { | ||
super.tearDown() | ||
|
||
DIContainer.shared.assembler = .init() | ||
} | ||
|
||
func test_noNamed() { | ||
DIContainer.shared.container.register(TestClass.self) { _ in | ||
return TestClass() | ||
} | ||
|
||
let _: TestClass = DIContainer.shared.resolver.resolve() | ||
} | ||
|
||
func test_named() { | ||
DIContainer.shared.container.register(TestClass.self, name: "TestName") { _ in | ||
return TestClass() | ||
} | ||
|
||
let _: TestClass = DIContainer.shared.resolver.resolve(name: "TestName") | ||
} | ||
|
||
func test_noNamed_arg1() { | ||
DIContainer.shared.container.register(TestClass.self) { _, arg1 in | ||
return TestClass(arg1: arg1) | ||
} | ||
|
||
let _: TestClass = DIContainer.shared.resolver.resolve(argument: 1) | ||
} | ||
|
||
func test_noNamed_arg2() { | ||
DIContainer.shared.container.register(TestClass.self) { _, arg1, arg2 in | ||
return TestClass(arg1: arg1, arg2: arg2) | ||
} | ||
|
||
let _: TestClass = DIContainer.shared.resolver.resolve(arguments: 1, 2) | ||
} | ||
|
||
func test_noNamed_arg3() { | ||
DIContainer.shared.container.register(TestClass.self) { _, arg1, arg2, arg3 in | ||
return TestClass(arg1: arg1, arg2: arg2, arg3: arg3) | ||
} | ||
|
||
let _: TestClass = DIContainer.shared.resolver.resolve(arguments: 1, 2, 3) | ||
} | ||
|
||
func test_needResolve() { | ||
DIContainer.shared.container.register(Foo.self) { _ in | ||
return Foo() | ||
} | ||
|
||
DIContainer.shared.container.register(TestClass.self) { resolver in | ||
let foo: Foo = resolver.resolve() | ||
return TestClass(foo: foo) | ||
} | ||
|
||
let _: TestClass = DIContainer.shared.resolver.resolve() | ||
} | ||
|
||
} | ||
|
||
final class Foo { | ||
|
||
init() {} | ||
|
||
} | ||
|
||
final class TestClass { | ||
|
||
let foo: Foo | ||
|
||
let arg1: Int | ||
|
||
let arg2: Int | ||
|
||
let arg3: Int | ||
|
||
init(foo: Foo = .init(), arg1: Int = 1, arg2: Int = 2, arg3: Int = 3) { | ||
self.foo = foo | ||
self.arg1 = arg1 | ||
self.arg2 = arg2 | ||
self.arg3 = arg3 | ||
} | ||
|
||
} |