-
Notifications
You must be signed in to change notification settings - Fork 72
Runtime arguments
Sometimes you need to register components that depend on some runtime arguments. For that you can register this component with a factory that accepts this parameter. When you resolve this component you will need to provide a value for this argument and it will be propagated to the factory:
container.register() { (url: String) in URLSessionNetworkLayer(baseURL: url) as NetworkLayer }
let network = try! container.resolve(arguments: "http://prod.myapi.com/api/") as NetworkLayer
-
Dip supports up to 6 runtime arguments. If that is not enougth you can extend
DependencyContainer
to support more arguments. However, if you find yourself thinking about adding more runtime arguments, stop and think about your design instead. Having too many dependencies could be a sign of some problem in your architecture, so we strongly suggest that you refrain from doing so; six runtime arguments is already a lot. -
Types, number and order of arguments matters and you can register different factories with different set of runtime arguments for the same protocol. To resolve using one of this factory you will need to pass runtime arguments of the same types, number and in the same order to
resolve
as you used inregister
method. -
Always explicitly specify types of runtime arguments. It will make your registrations more clear and will help you to avoid mistakes when Swift type inference will infer argument's type as
Optional
. The following code will fail to resolveURLSessionNetworkLayer
because Swift type system will infer factory argument type asString?
, butString
value is provided toresolve
:
class URLSessionNetworkLayer {
init(baseURL: String?) { ... }
}
container.register() { url in URLSessionNetworkLayer(baseURL: url) as NetworkLayer }
//this will throw an error
let network = try! container.resolve(arguments: "http://prod.myapi.com/api/") as NetworkLayer
container.register() { (url: String) in URLSessionNetworkLayer(baseURL: url) as NetworkLayer }
//this will successfully resolve
let network = try! container.resolve(arguments: "http://prod.myapi.com/api/") as NetworkLayer
Warning: container does not check values of runtime arguments when resolving components. So if you try to resolve new instance with another values of runtime arguments you may get back the same instance as before depending on the scope used to register its type (
shared
or only of singleton scopes)