更好地理解依赖注入 - 解析新实例?

如何解决更好地理解依赖注入 - 解析新实例?

我的工作要求我专注于依赖注入。对于后代,我在 Swift/SwiftUI 中使用它,尽管我相信我对概念的缺乏理解比语言更固有。

我创建了一个依赖注入容器,可以用来注册和解析类型和组件。因此;

protocol MyContainerProtocol {
    func register<Component>(type: Component.Type,component: Any)
    func resolve<Component>(type: Component.Type) -> Component?
}

final class MyContainer: MyContainerProtocol {
    
    static let shared = DependencyContainer()
    private init() { }
    
    var components: [String: Any] = [:]
    
    func register<Component>(type: Component.Type,component: Any) {
        components["\(type)"] = component
    }
    
    func resolve<Component>(type: Component.Type) -> Component? {
        return components["\(type)"] as? Component
    }
}

这将在下面变得相关,但我的项目中有一个类,名为 VideoProcessor;

class VideoProcessor: SomeProtocol {
    var codec: String
    var format: String

    init(codec: String,format: String) {
      self.codec = codec
      self.format = format
    }
}

在应用程序生命周期的早期,我正在注册组件。例如;

let container = DependencyContainer.shared
container.register(type: VideoProcessor.self,component: VideoProcessor(codec: "H264",format: "MP4"))
...
let processor = container.resolve(type: VideoProcessor.self)!

我的困惑: 要求我解析一个类型的实例,而不必在注册时构造它。实际上,每次解析时,我都被要求解析已注册类型的新实例。在我看来,这意味着我的代码类似于;

let container = DependencyContainer.shared
container.register(type: VideoProcessor.self)
...
let processorA = container.resolve(type: VideoProcessor.self)!
processorA.codec = "H264"
processorA.format = "MP4"

let processorB = container.resolve(type: VideoProcessor.self)!
processorB.codec = "H265"
processorB.format = "MOV"

但是,VideoProcessor 有自己的依赖项,这让我不确定如何注册类型。

我不确定我的问题是否存在于我的依赖容器的构建方式、我的类的构建方式,或者我只是不理解被问到的问题。即使查看像 SwinjectDIP 这样的流行 Swift 库,我也不能完全看出我的 Container 做错了什么(或者这是否是 Factory 方法的用武之地)。

解决方法

您需要添加一个额外的寄存器功能。

protocol MyContainerProtocol {
  func register<Component>(type: Component.Type,component: Any)
  func register<Component>(type: Component.Type,builder: @escaping (MyContainerProtocol) -> Component)
  func resolve<Component>(type: Component.Type) -> Component?
}

final class MyContainer: MyContainerProtocol {
  
  static let shared = MyContainer()
  private init() { }
  
  var components: [String: Any] = [:]
  
  func register<Component>(type: Component.Type,component: Any) {
    components["\(type)"] = component
  }
  
  func register<Component>(type: Component.Type,builder: @escaping (MyContainerProtocol) -> Component) {
    components["\(type)"] = builder
  }
  
  func resolve<Component>(type: Component.Type) -> Component? {
    if let singleton = components["\(type)"] as? Component {
      return singleton
    }
    
    if let builder = components["\(type)"] as? (MyContainerProtocol) -> Component {
      return builder(self)
    }
    
    return nil
  }
}

然后它在呼叫站点看起来像这样:

struct Animal {
  let type: String
  let id = UUID()
}

struct Person {
  let name: String
  let pet: Animal
  let id = UUID()
}

class ComplicatedNetworkStack {
  let id = UUID()
  /// so much stuff in here
}

MyContainer.shared.register(type: Animal.self) { _ in Animal(type: "Dog") }
MyContainer.shared.register(type: Person.self) { container in
  Person(
    name: "Joe Dirt",pet: container.resolve(type: Animal.self)!
  )
}

MyContainer.shared.register(type: ComplicatedNetworkStack.self,component: ComplicatedNetworkStack())

如果您在 Playground 中运行该代码并解析 PersonAnimal 几次,您会看到 UUID 全都不同,而 ComplicatedNetworkStack 的 id 是一样。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?