0

我正在努力解决注入依赖问题。现在问题来了,在委托模式的情况下如何使用接口隔离原则?我正在使用 Swinject 框架进行依赖注入。我该如何解决这个问题?

class Client {
    private var interface: ParentInterface

    ...

    func execute() {
        interface = globalContainer.resolve(ParentInterface.self)
        interface?.parentMethod()
    }
}
protocol ParentInterface {
    func parentMethod()
}

class Parent: ParentInterface, ParentDelegate {

    // Dependency
    private var child: Child? //  I WANT TO USE AN PROTOCOL HERE, NOT THE CLASS

    init(childReference: Child) {
        self.child = childReference
        self.child?.delegate = self //  But if I use the protocol I cant access the delegate property
    }

    public func parentMethod() {
        let result = calcSomething()

        // Access child class interface method
        child?.childMethod(result)
    }
    ...
}

孩子班,到目前为止没有什么异常。

protocol ParentDelegate: class {
    func delagteMethod(value: Double)
}

protocol ChildInterface {
    func childMethod(_ result: Double)
}

class Child: ChildInterface {

    weak var delegate: ParentDelegate?

    ...

    private func delagteMethod() {
      delegate?.delagteMethod(value: someValue)
    }

}

但是要正确注入依赖项,我需要一个协议而不是直接的类引用,对吗?像这样:


//  Would like to
container.register(ParentInterface.self) { r in
    Parent(childInterface: r.resolve(ChildInterface.self)!)
} 

//  Only way I get it working without interface
container.register(ParentDelegate.self) { r in
    Parent(childClass: Child())
}

container.register(ChildInterface.self) { _ in Child() }
    .initCompleted { r, c in
        let child = c as! Child
        child.delegate = r.resolve(ParentDelegate.self) 
}


简而言之,我在绕圈子。如果我为子类使用接口,我无法访问委托属性,如果我使用类引用,我无法合理地模拟/存根接口方法。

我错过了什么?提前非常感谢!

4

1 回答 1

1

我建议self.child?.delegate = selfParent构造函数中删除,原因有两个:

  1. DI 框架不应该负责连接所有依赖项吗?
  2. 特别是在 Swinject 中,这可能会导致不正确的依赖关系,请参阅文档中的注释

我倾向于使用的模式或多或少是您想出的:

class Parent: ParentInterface, ParentDelegate { 
    init(child: ChilInterface) { self.child = child }
}

class Child: ChildInterface {
    weak var parent: ParentDelegate?
}

container.register(ParentInterface.self) { Parent(child: $0.resolve(ChildInterface.self)!) }
    .implements(ParentDelegate.self)

container.register(ChildInterface.self) { _ in Child() }
    .initCompleted { ($1 as! Child).delegate = $0.resolve(ParentDelegate.self) }

此外,如果您想摆脱强制转换,您可以执行以下操作:

container.register(Child.self) { _ in Child() }
   .implements(ChildInterface.self)
   .initCompleted { $1.delegate = $0.resolve(ParentDelegate.self) }
于 2019-09-19T14:27:46.540 回答