ios - 如何在我的工厂解析器中注册 2 个具有相同抽象接口(interface)的依赖项?

标签 ios swift dependency-injection factory object-identity

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

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)
})

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

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

最佳答案

当您使用 ObjectIdentifier 时,它不能在当前工作作为字典中的键,typealias不改变。

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

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

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

您也可以考虑使用泛型来指定 HTTPClient正在使用的接口(interface),并扩展RemoteImageDataLoader根据客户的类型采取相应的行动。

关于ios - 如何在我的工厂解析器中注册 2 个具有相同抽象接口(interface)的依赖项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61078548/

相关文章:

ios - 制作圆形动画的正确方法是什么?

eclipse - org.eclipse.e4.core.di.InjectionException : java. lang.NullPointerException

.net - DI- Type 类型的动态参数,其中 type 是父对象类型

ios - MKPointAnnotation - 默认显示标题和动画?

swift - UTF8 到 Base 2 表示 Swift

iphone - 有没有快速缩放图像的方法?

swift - 在 Swift 中更改 UIBezierPath 的颜色

android - 使用 Dagger-2 和 Autofactory 时实现辅助注入(inject)的问题

ios - Swift - 如何检查 TableView 是否为空

ios - 如何获取从 Storyboard实例化的 UIButton 类中的 View Controller 实例