본문 바로가기
Swift

ObjectIdentifier을 이용한 DI - 2

by zinozino 2022. 4. 13.

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 마지막시간에 실제 사용상 편하게 할 수 있는 방법과

실제 현재 작업 중인 프로젝트에 적용한 것을 소개하도록 하겠습니다.

 

개발 아모르직다...

 

참고자료

https://github.com/Swinject/Swinject

'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