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 を使用したいのですが、リーフ エンティティには引き続き Containers を使用します。Assembly をコンテナの親として渡すことは可能ですか? または、それを達成する他の方法はありますか?
4

1 に答える 1

3

1. Should I resolve instances through assembly, not through container?

It's up to you whether you use the assembly feature. It is used to manage grouping of dependencies. Since it looks you already manage the groups of dependencies by ParentContainer and ChildContainer, I think you don't have to use assemblies.

People who have used Typhoon might prefer the feature. People who have used another register/resolve type DI container might prefer organizing container structures by themself.

2. What is the purpose of func loaded(resolver: ResolverType) method? should I retain resolver? Can it lead to retain cycle?

It is called after all assemblies are applied to a container in order to do something that cannot run during assemble method of an Assembly. It is called by the system of Swinject like viewDidLoad of UIViewController called by the UIKit system. The documentation about loaded or a unit test might help you understanding loaded function.

You shouldn't store the resolver parameter. (Actually I don't see usecases to store it because Assembler doesn't keep references to assemblies, which will be released after you instantiate Assembler. Even if you store it, no retain cycle is caused.)

3. I'd like to have TopLevelAssembly, but still use Containers for leaf entitites. Is it possible to pass Assembly as a parent for a container? Or are there any other way to achieve it?

I didn't catch your context about the TopLevelAssembly and leaf entities. I will be able to update my answer later if you add more details.

Here are some comments to the question parts: You cannot pass an Assembly instance because the initializer of Container is init(parent: Container? = nil), which takes an instance of Container. Another way to achieve it might be just keeping the top level as Container. (Or I have to update Swinject to support the scenario.)

My answer might not be perfect but I hope it helps you implement the service locator pattern.

于 2016-01-11T11:05:34.197 に答える