Как реализовать инверсию управления в Swift - PullRequest
0 голосов
/ 30 марта 2020

Я реализовал легкий контейнер Io C в Swift. Реализация работает, но терпит неудачу при использовании циклических зависимостей. Круговые зависимости установлены, но равны нулю, когда родительский объект разрешен.

class Definition<T> { 

  // MARK: - Properties

  typealias DefinitionBuilder = () throws -> T
  let definitionBuilder: DefinitionBuilder
  private let container: DependencyContainer

  // MARK: - Init

  init(definitionBuilder: @escaping DefinitionBuilder, container: DependencyContainer) {
    self.definitionBuilder = definitionBuilder
    self.container = container
  }

  @discardableResult public func resolveProperties(_ block: @escaping (DependencyContainer, T) throws -> Void) -> Definition {
    do {
      try block(container, definitionBuilder())
    } catch let defError {
      print(defError)
    }
    return self
  }
}

class DependencyContainer {

  // MARK: - Properties

  var definitions = [Any]()

  // MARK: - Register

  func register<T>(builder: @escaping Definition<T>.DefinitionBuilder) -> Definition<T> {
    let definition = Definition(definitionBuilder: builder, container: self)
    definitions.append(definition)
    return definition
  }

  // MARK: - Resolve

  enum ResolveError: Error {
    case notRegistered(Any)
  }

  func resolve<T>() throws -> T {
    guard let declaration = (definitions.first { ($0 as? Definition<T>) != nil }) as? Definition<T> else {
      throw ResolveError.notRegistered(T.self)
    }

    return try declaration.definitionBuilder()
  }
}

Пример отказа

class Foo {
  var bar: Bar
  init(bar: Bar) {
    self.bar = bar
  }
}

class Bar {

  var foo: Foo?
}


container.register { Foo(bar: try self.container.resolve()) }

container.register { Bar() }
    .resolveProperties { (container, bar) -> () in
      bar.foo = (try container.resolve() as Foo)
  }

let foo = try! container.resolve() as Foo
let bar = try! container.resolve() as Bar

foo.bar // this is not nil
bar.foo // this is nil when it shouldn't be

foo.bar === bar  // this should be true but returns false! 

Я ожидаю, что создаются несколько экземпляров типов, поэтому foo.bar === bar возвращает false.

Есть идеи, как это исправить? Заранее спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...