Swinject:迁移到程序集

Swinject: migrating to assemblies

我在我的项目中使用很棒的 Swinject 作为 DI,但我在没有程序集的情况下使用它(当我开始使用 Swinject 时,还没有程序集)。

我目前使用 Containers 的模式是:

class ParentContainer {

    private let container: Container

    init(parentContainer: Container?) {
        container = Container(parent: parentContainer)

        container.register....
    }

    func myTopLevelController() -> MyTopController {
        let controller = container.resolve....
        controller.container = self // controller holds its container
        return controller
    }

    func childContainer() -> ChildContainer {
        return ChildContainer(parentContainer: container)
    }

}


class ChildContainer {

    private let container: Container

    init(parentContainer: Container?) {
    ....
}

使用该配置:

现在我正在尝试申请 Assembly。据我所知,my 容器现在将符合 AssemblyType 协议。但是我有些困惑:

  1. 我应该通过程序集而不是通过容器来解析实例吗?
  2. func loaded(resolver: ResolverType) 方法的目的是什么?我应该保留解析器吗?会导致retain cycle吗?
  3. 我想要 TopLevelAssembly,但仍将容器用于叶实体。是否可以将 Assembly 作为容器的父级传递?或者还有其他方法可以实现吗?

1.我应该通过程序集而不是容器来解析实例吗?

是否使用汇编功能由您决定。它被使用 to manage grouping of dependencies。由于看起来您已经通过 ParentContainerChildContainer 管理依赖项组,我认为您不必使用程序集。

使用过 Typhoon 的人可能更喜欢该功能。使用过其他 register/resolve 类型 DI 容器的人可能更喜欢自己组织容器结构。

2。 func loaded(resolver: ResolverType) 方法的目的是什么?我应该保留解析器吗?会不会导致retain cycle?

在将所有程序集应用于容器后调用它,以便在 Assemblyassemble 方法期间执行 运行 不能执行的操作。它被Swinject系统调用,就像UIKit系统调用viewDidLoad of UIViewController一样。 The documentation about loaded or a unit test 可能会帮助您理解 loaded 函数。

您不应存储 resolver 参数。 (其实我没有看到用例来存储它,因为Assembler不保留对程序集的引用,它会在你实例化后释放Assembler。即使你存储它,也不会导致保留循环。 )

3.我想要 TopLevelAssembly,但仍将容器用于叶实体。是否可以将 Assembly 作为容器的父级传递?或者还有其他方法可以实现吗?

我没听懂您关于 TopLevelAssembly 和叶实体的上下文。如果您添加更多详细信息,我将能够稍后更新我的答案。

以下是对问题部分的一些评论:您不能传递 Assembly 实例,因为 Container 的初始化程序是 init(parent: Container? = nil),它采用 Container 的实例.实现它的另一种方法可能只是将顶层保持为 Container。 (或者我必须更新 Swinject 以支持该场景。)

我的回答可能并不完美,但我希望它能帮助您实现服务定位器模式。