Skip to content

Multi-injection #14

@ilyapuchka

Description

@ilyapuchka

Sometimes it can be useful to register several implementations for the same protocol and resolve them as an array. Imagine that you have different authorisation services, for instance via Facebook, Twitter and Google, that all implement a common protocol, and you want to present the list of all possible services so that user can choose one of them but your code does not care what concrete service he chose, you just work with it via that common protocol.

With Dip we can do that only with tags, associating different implementations of the same protocol with different tags and resolve them using the same tags. Though it works it introduces coupling between independent parts of the system - point of registration and points of resolution.

protocol OAuthService {
    func doLogin()
}

class FacebookOAuth: OAuthService {
    func doLogin() {
        print("login with facebook")
    }
}

class TwitterOAuth: OAuthService {
    func doLogin() {
        print("login with twitter")
    }
}

class GoogleOAuth: OAuthService {
    func doLogin() {
        print("login with google")
    }
}

let container = DependencyContainer { container in
    container.register(tag: "facebook") { FacebookOAuth() as OAuthService }
    container.register(tag: "twitter") { TwitterOAuth() as OAuthService }
    container.register(tag: "google") { GoogleOAuth() as OAuthService }
}

let services: [OAuthService] = [
    container.resolve(tag: "facebook"),
    container.resolve(tag: "twitter"),
    container.resolve(tag: "google")
]

services[Int(arc4random_uniform(UInt32(3)))].doLogin()

Other IoC containers (like Ninject for .Net) has this feature. The obvious consequence of allowing multiple bindings to the same protocol is that how you resolve them not as an array but as a single instance, what binding (definition in case of Dip) you should choose. Ninject offers different styles of attributes or runtime context checks that are very specific for .Net. If there is no constraints that resolution result is ambiguous and exception is thrown.

Do we need such feature in Dip and if yes than how we should solve the ambiguity problem?

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions