# Resolver: Named Instances ## Why Name a Registration? Because named registrations and resolutions let you change the behavior of the app and determine just which service or value should be resolved for a given type. Dependency Injection is powerful tool, but named registrations take the entire concept to an entriely different level. ## Registering a Name Resolver 1.3 adds a `Name` space to Resolver similar to that of `Notificiations.Name`. Registering a name lets you use Xcode's autocompletion feature for registrations and to resolve named instances and also ensures that you don't accidentally use "fred" in one place, "Fred" in another, and "Freddy" somewhere else. You define your own names by extending `Resolver.Name` as follows: ```swift extension Resolver.Name { static let fred = Self("Fred") static let barney = Self("Barney") } ``` Once defined your names can be used in the `name` parameter when registering services. Here we define two instances of the same protocol, distinguished by name. ```swift register(name: .fred) { XYZServiceFred() as XYZServiceProtocol } register(name: .barney) { XYZServiceBarney() as XYZServiceProtocol } ``` Once defined and registered, names can be used during the resolution process to pick just which version of the service you desire. ```swift let service: XYZServiceProtocol = resolve(name: .fred) // or @Injected(name: .barney) var service: XYZServiceProtocol ``` ## Using Named Value Types In addition to services you can also register value types and parameters for later resolution. However, since Resolver registers objects and values based on type inference, the only way to tell one `String` from another `String` is to name it. We start once again by defining the names we want to use, in this case `appKey` and `token`. ```swift extension Resolver.Name { static let appKey = Self("appKey") static let token = Self("token") } ``` We then register some strings using our `.appKey` and `token` names. ```swift register(name: .appKey) { "12345" } register(name: .token) { "123e4567-e89b-12d3-a456-426614174000" } ``` Which can then be used when we resolve our services. The following code shows how a factory resolves a String parameter named `.appKey`, which passes the resulting string value to the `XYZSessionService` initialization function. ```swift register { XYZSessionService(key: resolve(name: .appKey)) } ``` This is a good way to get authentication keys, application keys, and other values to the objects that need them. ## Mocking Data We can also use names to control access to mocked data. Consider the following set of registrations. ```swift extension Resolver.Name { static let data = Self("data") static let mock = Self("mock") } register(name: .data) { XYXService() as XYZServicing } register(name: .mock) { XYXMockService() as XYZServicing } register { resolve(name: .name(fromString: Bundle.main.infoDictionary!["mode"] as! String)) as XYZServicing } ``` Here we've registered the XYZServicing protocol three times: once with the name space `.data`, and then again version with the name space `.mock`. The third registration, however, has no name. Instead, it gets a string from the app's info.plist and asks Resolver to resolve an instance with the proper type and with the proper name. Let's see it in use by a client. ```swift @Injected var service: XYZServicing ``` The client just asks Resolver for an instance of `XYZServicing`. Behind the scenes, however, and depending upon how the app is compiled and how the "mode" value is set in the app's plist, one build will get actual data, while the other build will get mock data. And as long as XYXMockService complies with the XYZServicing protocol, the client doesn't care. Nor should it. One final note here is that we registered `Resolver.Name` instances, but in our factory we converted `mode` into a `Name` based on the value of the string we pulled from the plist. Just be careful when you're doing this and make sure your passed strings actually match names actually registered in the app. ## Changing Behavior On The Fly Finally, consider the next pair of registrations: ```swift extension Resolver.Name { static let add = Self("add") static let edit = Self("edit") } register(name: .add) { XYZViewModelAdding() as XYZViewModelProtocol } register(name: .edit) { XYZViewModelEditing() as XYZViewModelProtocol } ``` Here we're registering two instances of the same protocol, `XYZViewModelProtocol`. But one view model appears to be specific to adding things, while the other's behavior leans more towards editing. ```swift class ViewController: UIViewController, Resolving { var editMode: Bool = true // set, perhaps, by calling segue lazy var viewModel: XYZViewModelProtocol = resolver.resolve(name: editMode ? .edit : .add)! } ``` Now the view controller gets the proper view model for the job. The `lazy var` ensures that the viewModel resolution doesn't occur until after the viewController is instantiated and `prepareForSegue` has had a chance to correctly set `editMode`. If you're using Resolver's property wrappers for injection, you can also do the same with `@LazyInjected`. ```swift class NamedInjectedViewController: UIViewController { var editMode: Bool // set, perhaps, by calling segue @LazyInjected var viewModel: XYZViewModelProtocol override func viewDidLoad() { super.viewDidLoad() $viewModel.name = editMode ? .edit : .add viewModel.load() } } ``` Again, just make sure you set the property name *before* using the wrapped `viewModel` for the first time. ## Using String Literals and String Variables Name spaces are better than simple string literals. Use them. That said, you should be aware that `Name` supports the `ExpressibleByStringLiteral` protocol, which means that you can also use a string *literal* to register and resolve your instances (e.g. `resolve(name: "Fred")`). String *variables*, however, are *not* automatically converted. If you're trying to translate a string variable to a `Name`, you either need to initialize it directly `Resolver.Name(myString)`, or do as we did in a previous example using the `.name(fromString: myString)` syntax. ```swift viewModel = resolver.optional(name: .name(fromString: type)) ``` Be aware that string literal support exists primarily for backwards compatibility with earlier versions of Resolver and that raw string paramaters will probably become deprecated in a future instance of Resolver. *Name spaces are based on a PR concept submitted by [Artem K./DesmanLead](https://github.com/DesmanLead).*