Я реализовал легкий контейнер 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.
Есть идеи, как это исправить? Заранее спасибо.