Skip to content

Commit

Permalink
Prepare 1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
woin2ee committed Nov 17, 2023
1 parent 6cfdd8d commit 2e8be66
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 16 deletions.
16 changes: 16 additions & 0 deletions Package.resolved
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
}
26 changes: 18 additions & 8 deletions Package.swift
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")
]
)
]
)
25 changes: 25 additions & 0 deletions Sources/SwinjectExtension/DIContainer.swift
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
}

}
52 changes: 52 additions & 0 deletions Sources/SwinjectExtension/Resolver+resolve.swift
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
}

}
14 changes: 12 additions & 2 deletions Sources/SwinjectExtension/SwinjectExtension.swift
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)
}
96 changes: 90 additions & 6 deletions Tests/SwinjectExtensionTests/SwinjectExtensionTests.swift
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
}

}

0 comments on commit 2e8be66

Please sign in to comment.