1편에서 ObjectIdentifier을 활용하여 DI 를 할 수 있는 DependencyInjecter 클래스를 만들었습니다.
객체를 등록하고 빼내고 하는 기본기능을 만들어보았는데요. 만약 같은걸 두 개 등록 하고 싶을 때가 있을 겁니다.
바로 아래처럼!
let dependencyInjecter = DependencyInjecter()
dependencyInjecter.register(MovieRepository.self) { _ in
MovieRepositoryImpl()
}
dependencyInjecter.register(MovieRepository.self) { _ in
MovieRepositoryImpl2()
}
dependencyInjecter.printKeys()
//=================
//[ObjectIdentifier(0x00007fff808b9aa0)]
//=================
BUT
ObjectIdentifier를 같으면 기존에 등록되어있는 것을 사용하려 하니 키값이 하나만 나오게 됩니다.
다음 시간까지 두 개의 기능 확장 중 첫 번째는
"같은 타입도 다르게 등록될 수 있게 하자"
그렇게 하기 위해서..
타입 이외에 구분할 수 있는 하나의 값이 더 필요할 것 같은데요...
protocol DependencyInjectable {
func register<T>(_ type: T.Type, name: String?, closure: (DependencyInjectable) -> (T))
func resolve<T>(_ anyClassType: T.Type, name: String? ) -> T?
}
일단 name이라고 이름 짓고 파라미터로 받을 수 있게 하고
받지 않고 기존처럼도 사용할 수 있도록 기본값을 넣어주고
그리고 이제 내부에서 ObjectIdentifier값과 받은 name을 조합하여 key값을 만들겁니다.
struct InjectableKey: Hashable {
let identifier: ObjectIdentifier
let name: String
//MARK: - INITIALIZE
init(identifier: ObjectIdentifier, name: String) {
self.identifier = identifier
self.name = name
}
//MARK: - HASHABLE
func hash(into hasher: inout Hasher) {
self.identifier.hash(into: &hasher)
self.name.hash(into: &hasher)
}
}
기존 ObjectIdentifier 과 name을 받을 수 있는
구조체를 만들고 Hashable을 따르도록 하였습니다.
//DependencyInjecter
func register<T>(_ type: T.Type,name: String? = nil, closure: (DependencyInjectable) -> (T)) {
let objId = ObjectIdentifier(type)
let key = InjectableKey(identifier: objId, name: name ?? "")
guard objectMap[key] == nil else {
return
}
objectMap[key] = closure(self) as AnyObject
}
실제 사용하는 곳에서 이제 ObjectIdentifier로 키값을 만드는게 아닌 InjectableKey를 넣었습니다.
이제 어떻게 동작하는지 보도록 하겠습니다.
dependencyInjecter.register(MovieRepository.self,name: "iron man") { _ in
MovieRepositoryImpl()
}
dependencyInjecter.register(MovieRepository.self) { _ in
MovieRepositoryImpl2()
}
dependencyInjecter.printKeys()
//=================
//[Injectable.InjectableKey(identifier: ObjectIdentifier(0x00007fff808b7168), name: ""),
//Injectable.InjectableKey(identifier: ObjectIdentifier(0x00007fff808b7168), name: "iron man")]
//=================
name으로 구분하면 이제 2개로 구분하여 사용 할 수 있습니다.
ObjectIdentifier 마지막시간에 실제 사용상 편하게 할 수 있는 방법과
실제 현재 작업 중인 프로젝트에 적용한 것을 소개하도록 하겠습니다.
개발 아모르직다...
참고자료
'Swift' 카테고리의 다른 글
FP에서 Setter 사용법 (0) | 2022.12.10 |
---|---|
Custom Operator => (0) | 2022.12.02 |
Currying (2) | 2022.11.30 |
Custom Operator |> (2) | 2022.11.29 |
ObjectIdentifier을 이용한 DI (3) | 2022.04.06 |