Skip to content

Named definitions

Ilya Puchka edited this page Apr 28, 2016 · 4 revisions

Sometimes you need to register different factories or different implementations of the same protocol. DependencyContainer does not capture the concrete type that you instantiate or any implementation details of registered factory, so if you try this the latest definition will override a previous one:

container.register() { URLSessionNetworkLayer(baseURL: "http://prod.myapi.com/api/") as NetworkLayer }
container.register() { URLSessionNetworkLayer(baseURL: "http://dev.myapi.com/api/") as NetworkLayer }

let network = try! container.resolve() as NetworkLayer
print(network.baseURL) // http://dev.myapi.com/api/

To solve that you can use named definitions by providing tag parameter to register method.

  • If you provide a tag value in the parameter to register, it will associate created definition with this tag;
  • When you provide a tag value to resolve, container will try to find a matching definition associated with this tag. If it doesn't find any, it will fallback to a matching definition not associated with any tag.
  • Tags can be of any type that conforms to DependencyTagConvertible protocol. String and Int conform to this protocol, RawRepresentable type with String or Int raw value types provides default implementation of DependencyTagConvertible.
enum Environment: String, DependencyTagConvertible {
    case Production
    case Development
}

container.register(tag: Environment.Production) { URLSessionNetworkLayer(baseURL: "http://prod.myapi.com/api/") as NetworkLayer }
container.register(tag: Environment.Development) { URLSessionNetworkLayer(baseURL: "http://dev.myapi.com/api/") as NetworkLayer }

let networkLayer = try! container.resolve(tag: Environment.Production) as NetworkLayer
print(network.baseURL) // http://prod.myapi.com/api/

If all definitions of the component are registered with a tag then you will not be able to resolve this component without providing a tag.