1

我有一个依赖容器,看起来像这样 -

public protocol DependencyContainer {
  typealias FactoryClosure = (Self) -> AnyObject
  func register<Service>(type: Service.Type, closure: @escaping FactoryClosure)
  func resolve<Service>(type: Service.Type) -> Service
}
public final class CoreDependencyContainer: DependencyContainer {

  private var services: Dictionary<ObjectIdentifier, FactoryClosure> = [:]

  public func register<Service>(type: Service.Type, closure: @escaping FactoryClosure) {
    services[ObjectIdentifier(type)] = closure
  }

  public func resolve<Service>(type: Service.Type) -> Service {
    if let service = services[ObjectIdentifier(type)]?(self) as? Service {
      return service
    }
    preconditionFailure("Could not resolve service for \(type)")
  }

}

我有一些服务注册如下:

dependencies.register(type: RemoteImageDataLoader.self, closure: { container in
  let httpClient = container.resolve(type: HTTPClient.self)
    return RemoteImageDataLoader(client: httpClient)
})

但是,我想注册 2 个符合抽象类型的服务RemoteImageDataLoader

dependencies.register(type: RemoteImageDataLoader.self, closure: { container in
  let httpClient = container.resolve(type: HTTPClient.self)
    return RemoteImageDataLoader(client: httpClient)
})

dependencies.register(type: RemoteImageDataLoader.self, closure: { container in
  let httpClient = container.resolve(type: AuthenticatedHTTPClient.self)
    return RemoteImageDataLoader(client: httpClient)
})

这显然不会起作用,因为第二个条目将替换services字典中的第一个条目。

我试图创建一个typealias来代替使用,但这不起作用。

dependencies.register(type: RemoteImageDataLoader.self, closure: { container in
  let httpClient = container.resolve(type: HTTPClient.self)
    return RemoteImageDataLoader(client: httpClient)
})

typealias AuthRemoteImageLoader = RemoteImageDataLoader

dependencies.register(type: AuthRemoteImageLoader.self, closure: { container in
  let httpClient = container.resolve(type: AuthenticatedHTTPClient.self)
    return RemoteImageDataLoader(client: httpClient)
})

在这种情况下如何注册第二个依赖项?

我想避免创建 2 个版本,RemoteImageDataLoader因为唯一的区别是注入的HTTPClient实例。

4

1 回答 1

1

ObjectIdentifier在您用作字典中的键时不起作用,它typealias不会改变。

您基本上是两次注册同一个对象。

创建一个符合相同接口的空协议。您还需要扩展您以符合新的空接口,否则您的resolve方法将抛出一个preconditionFailure

protocol AuthRemoteImageLoader: RemoteImageDataLoader { }
extension RemoteImageDataLoader: AuthRemoteImageLoader { }

您还可以考虑使用泛型来指定正在使用的接口,并根据客户端的类型进行相应的HTTPClient扩展。RemoteImageDataLoader

于 2020-04-07T13:59:50.130 回答