Skip to content

Container Inheritance

Andrey Pleshkov edited this page Jan 12, 2019 · 4 revisions

It's very common situation for a complex app to have two or even more containers. In this case it'd become necessary to organise an inheritance so a service from one container "sees" a service from another one.

Saber provides such inheritance via the @saber.dependsOn(OneContainer, AnotherContainer, ...) annotation. As you can see from the annotation signature it's a multiple inheritance.

Imagine two containers:

// @saber.container(AppContainer)
// @saber.scope(App)
protocol AppContaining {}

// @saber.container(UserContainer)
// @saber.scope(User)
// @saber.dependsOn(AppContainer)
protocol UserContaining {}

Let's create a Database service and attach it to the AppContainer. It provides a functionality of getting a User by an id from its underlying storage:

// @saber.scope(App)
// @saber.cached
// ^ It's cached to be reusable across the app
class Database {
    
    func user(id: String) -> User {
        return User()
    }
}

Then advance the UserContainer to be able to get configured with a user id. Let's do it via externals. Also we use a trick to provide an internal Swift type as a dependency here.

typealias UserId = String // the trick

// @saber.container(UserContainer)
// @saber.scope(User)
// @saber.dependsOn(AppContainer)
// @saber.externals(UserId)
// ^ HERE!
protocol UserContaining {}

Let's add a UserManager service to provide a current user:

// @saber.scope(User)
// @saber.cached
class UserManager {
    
    let currentUser: User
    
    // @saber.inject
    // - `database` will be taken from the `AppContainer`
    // - `userId` will be taken from the `UserContainer` external
    init(database: Database, userId: UserId) {
        self.currentUser = database.user(id: userId)
    }
}

Now we can use our containers:

let appContainer = AppContainer()

// ...

let currentUserId = ...
let userContainer = UserContainer(appContainer: appContainer, userId: currentUserId)

print(userContainer.userManager.currentUser)
Clone this wiki locally