Skip to content

Commit 76dffa4

Browse files
committed
update readme
1 parent d331a2c commit 76dffa4

2 files changed

Lines changed: 210 additions & 2 deletions

File tree

README-ko.md

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ Swift 의존성 주입 컨테이너는 Swift 애플리케이션에서 의존성
1111
- 편리한 의존성 주입을 위한 프로퍼티 래퍼.
1212
- 동적 모듈 등록 및 관리.
1313
- 선언적 모듈 등록을 위한 결과 빌더 구문.
14-
- 모듈 및 주입 키 스캐닝을 위한 디버그 유틸리티.
14+
- 주입 키와 자동 모듈을 발견하는 디버그 전용 스캐너.
15+
- `AutoModule``Container.autoRegisterModules()`를 통한 디버그 빌드 자동 모듈 등록.
1516

1617
## 요구사항
1718

@@ -70,6 +71,70 @@ struct Cat: Meow {
7071
}
7172
```
7273

74+
### Scanner와 자동 모듈 등록
75+
76+
DIContainer는 로드된 앱에서 주입 키와 자동 모듈을 발견하는 디버그 전용 스캐너를 제공합니다.
77+
78+
- `ModuleScanner`는 Objective-C 런타임으로 클래스를 스캔합니다.
79+
- `MachOLoader`는 로드된 Mach-O 이미지의 Swift 메타데이터를 스캔합니다.
80+
- `Container.autoRegisterModules()`는 스캔된 `AutoModule` 구현체 타입을 `Module`로 변환해 컨테이너를 구성합니다.
81+
82+
키와 구현체의 역할은 서로 다릅니다.
83+
84+
- `InjectionKey`는 의존성 계약을 정의합니다. `Value`는 보통 호출자가 의존하는 프로토콜이나 추상 타입입니다.
85+
- `AutoModule` 구현체는 실제 생성될 구체 타입입니다. `ModuleKeyType`은 이 구현체를 어떤 키로 등록할지 스캐너에게 알려줍니다.
86+
- `keyList`는 진단에 유용하지만, 자동 등록은 스캔된 `AutoModule` 구현체와 그 구현체의 `ModuleKeyType`을 기준으로 동작합니다.
87+
88+
아래 예제에서 `FooServiceKey``FooService`를 resolve 가능한 타입으로 노출하고, `FooServiceImpl`은 스캐너가 발견하는 실제 구현체입니다.
89+
90+
```swift
91+
final class FooServiceKey: InjectionKey {
92+
typealias Value = FooService
93+
}
94+
95+
protocol FooService {
96+
func doSomething()
97+
}
98+
99+
final class FooServiceImpl: AutoModule, FooService {
100+
typealias ModuleKeyType = FooServiceKey
101+
102+
func doSomething() {
103+
print("Foo")
104+
}
105+
}
106+
```
107+
108+
스캔 이후 DIContainer는 이 구현체를 다음과 같은 명시 등록과 같은 의미로 다룹니다.
109+
110+
```swift
111+
Module(FooServiceKey.self) {
112+
FooServiceImpl()
113+
}
114+
115+
// or
116+
```swift
117+
Module(FooServiceImpl.self)
118+
```
119+
120+
그다음 디버그 composition root에서 스캔된 모듈을 자동 등록할 수 있습니다.
121+
122+
```swift
123+
#if DEBUG
124+
Container.autoRegisterModules()
125+
#endif
126+
```
127+
128+
스캔 결과를 직접 확인할 수도 있습니다.
129+
130+
```swift
131+
let keys = ModuleScanner().keyList
132+
let modules = ModuleScanner().scanModuleList
133+
Container(modules: modules).build()
134+
```
135+
136+
Scanner API는 `#if DEBUG`에서만 컴파일됩니다. 진단, 데모, 테스트 등록에는 유용하지만, 프로덕션 composition은 명시적으로 구성하고 테스트로 보호하는 것을 권장합니다.
137+
73138
### Test
74139

75140
```shell

README.md

Lines changed: 144 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ The Swift Dependency Injection Container is a lightweight and flexible library d
1212
- Property wrappers for convenient dependency injection.
1313
- Dynamic module registration and management.
1414
- Result builder syntax for declarative module registration.
15-
- Debug utilities for module and injection key scanning.
15+
- Debug-only scanners for discovering injection keys and auto modules.
16+
- Automatic module registration for debug builds via `AutoModule` and `Container.autoRegisterModules()`.
1617

1718
## Requirements
1819

@@ -73,6 +74,148 @@ struct Cat: Meow {
7374
}
7475
```
7576

77+
# Dependency Injection Container
78+
79+
[English](README.md) | [한국어](README-ko.md)
80+
81+
## Overview
82+
83+
The Swift Dependency Injection Container is a lightweight and flexible library designed to facilitate dependency management in Swift applications. It provides a structured and type-safe approach to resolve dependencies throughout your codebase, promoting code reusability, testability, and maintainability.
84+
85+
## Features
86+
- Type-safe dependency resolution.
87+
- Lazy instantiation of dependencies.
88+
- Property wrappers for convenient dependency injection.
89+
- Dynamic module registration and management.
90+
- Result builder syntax for declarative module registration.
91+
- Debug-only scanners for discovering injection keys and auto modules.
92+
- Automatic module registration for debug builds via `AutoModule` and `Container.autoRegisterModules()`.
93+
94+
## Requirements
95+
96+
- Swift 5.9+
97+
98+
## Policy
99+
100+
- [DIContainer Policy (English)](docs/DIContainerPolicy.md)
101+
102+
## Installation
103+
104+
DIContainer is available [Swift Package Manager](https://swift.org/package-manager/).
105+
106+
### Swift Package Manager
107+
108+
in `Package.swift` add the following:
109+
110+
```swift
111+
dependencies: [
112+
.package(url: "https://github.com/minsOne/DIContainer.git", from: "1.0.0")
113+
]
114+
```
115+
116+
## Usage
117+
118+
### Basic Usage
119+
120+
First, register a key and module pair to a `Container`, where the module has concreate type. `Key` has `protocol type`, and `concreate type` is inheriting `protocol type`
121+
122+
```swift
123+
Container {
124+
Module(AnimalKey.self) { Cat() }
125+
}
126+
.build()
127+
```
128+
129+
Then get an instance from the container.
130+
131+
```swift
132+
@Inject(AnimalKey.self)
133+
var cat: Meow
134+
cat.doSomething() // prints "Meow.."
135+
// or
136+
Container[AnimalKey.self].doSomething() // prints "Meow.."
137+
```
138+
139+
Where definitions of the protocols and struct are
140+
141+
```swift
142+
class AnimalKey: InjectionKey {
143+
var type: Meow?
144+
}
145+
146+
protocol Meow {
147+
func doSomething()
148+
}
149+
150+
struct Cat: Meow {
151+
func doSomething() {
152+
print("Meow..")
153+
}
154+
}
155+
```
156+
157+
### Scanner and Automatic Module Registration
158+
159+
DIContainer includes debug-only scanners that discover injection keys and auto modules from the loaded app:
160+
161+
- `ModuleScanner` uses the Objective-C runtime to scan classes.
162+
- `MachOLoader` scans Swift metadata from loaded Mach-O images.
163+
- `Container.autoRegisterModules()` builds a container by converting scanned `AutoModule` implementation types into `Module` values.
164+
165+
The key and the implementation have different responsibilities:
166+
167+
- An `InjectionKey` defines the dependency contract. Its `Value` is usually a protocol or abstract type that callers depend on.
168+
- An `AutoModule` implementation provides the concrete type. Its `ModuleKeyType` tells the scanner which key should be used for registration.
169+
- `keyList` is useful for diagnostics, but automatic registration is driven by scanned `AutoModule` implementations and their `ModuleKeyType`.
170+
171+
In the example below, `FooServiceKey` exposes `FooService` as the resolvable type, and `FooServiceImpl` is the concrete implementation discovered by the scanner.
172+
173+
```swift
174+
final class FooServiceKey: InjectionKey {
175+
typealias Value = FooService
176+
}
177+
178+
protocol FooService {
179+
func doSomething()
180+
}
181+
182+
final class FooServiceImpl: AutoModule, FooService {
183+
typealias ModuleKeyType = FooServiceKey
184+
185+
func doSomething() {
186+
print("Foo")
187+
}
188+
}
189+
```
190+
191+
After scanning, DIContainer treats the implementation like this explicit registration:
192+
193+
```swift
194+
Module(FooServiceKey.self) {
195+
FooServiceImpl() as FooService
196+
}
197+
// or
198+
Module(FooServiceImpl.self)
199+
```
200+
201+
Then register all scanned modules in a debug composition root.
202+
203+
```swift
204+
#if DEBUG
205+
Container.autoRegisterModules()
206+
#endif
207+
```
208+
209+
You can also inspect scan results directly.
210+
211+
```swift
212+
let keys = ModuleScanner().keyList
213+
let modules = ModuleScanner().scanModuleList
214+
Container(modules: modules).build()
215+
```
216+
217+
Scanner APIs are compiled only under `#if DEBUG`. They are useful for diagnostics and demo/test registration, while production composition should remain explicit and covered by tests.
218+
76219
### Test
77220

78221
```shell

0 commit comments

Comments
 (0)