1

我在我的项目中为 DI 使用了很棒的Swinject,但我在没有程序集的情况下使用它(当我开始使用 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?) {
    ....
}

使用该配置:

  • 容器只要它们需要存活就可以存活(唯一持有对它们的引用的实体 - VC,可以使用依赖项)
  • 我可以停止使用/切换 DI 框架,Container甚至用手动构建替换(我的代码不知道任何框架),因为我的代码调用:let topController = ParentContainer().myTopLevelController()

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

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

1 回答 1

3

1.我应该通过组装而不是通过容器来解决实例吗?

是否使用装配功能取决于您。它用于管理依赖项的分组。由于看起来您已经通过ParentContainerand管理依赖项组ChildContainer,因此我认为您不必使用程序集。

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

2. func loaded(resolver: ResolverType) 方法的作用是什么?我应该保留解析器吗?它会导致保留周期吗?

在将所有程序集应用于容器后调用它,以执行assembleAssembly. 它由 Swinject 系统调用,就像viewDidLoadUIViewControllerUIKit 系统调用一样。有关loaded单元测试的文档可能会帮助您理解loaded功能。

您不应该存储resolver参数。(实际上我没有看到存储它的用例,因为Assembler不保留对程序集的引用,这些引用将在您实例化后释放Assembler。即使您存储它,也不会导致保留周期。)

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

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

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

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

于 2016-01-11T11:05:34.197 回答