A couple of days ago MacWire 0.8.0 got released. It contains a couple of changes and new features. But first, I’d like to thank Marcin Kubala for his contributions.
All of the changes are reflected in the guide to DI in Scala.
If you have multiple objects of the same type which you want to use as dependencies, you need to somehow differentiate between them if you want
wire to work (otherwise you’ll get a compile-time error). This can be now done with tags, inspired by the work of Miles Sabin:
1 2 3 4 5 6 7 8 9
class Berry() trait Black trait Blue case class Basket(blueberry: Berry @@ Blue, blackberry: Berry @@ Black) lazy val blueberry = wire[Berry].taggedWith[Blue] lazy val blackberry = wire[Berry].taggedWith[Black] lazy val basket = wire[Basket]
X @@ T is type
X tagged with tag
x.taggedWith[T] method is available on any type. Tags don’t have any runtime overhead, they are a purely compile-time construct.
As a bonus, your code will be more type-safe, as you won’t be able to use incorrectly tagged instances where a tag is required: tags follow the expected subtyping rules, so you can upcast a tagged instance to an untagged one, but you can’t cast an instance with one tag to an instance with another tag.
Wiring with anonymous function parameters
This feature is especially useful when creating factories. Before, wiring only took into account values from the enclosing method parameters, enclosing trait/class/object and parents. Now, parameters of any enclosing anonymous functions are taken into account as well, allowing to write for example the following:
1 2 3
class TaxCalculator(taxBase: TaxBase, …) lazy val taxCalculator = (taxBase: TaxBase) => wire[TaxCalculator]
Finally, there’s a new variant of
wireImplicit. When looking up values for a given constructor parameter, in addition to the usual lookup steps, an implicit lookup on the type is done. If this yields multiple values, a compile-time error is reported.
Note that if a parameter list is marked as implicit, an implicit lookup is done both for
wireImplicit. The difference with
wireImplicit is that it makes all parameters behave as if they were marked as implicit.
MacWire no longer does by-name parameter matching for enclosing method parameters. This was a special-case which we think was rarely used (if at all), and only caused confusion.
The 0.8.0 release will be the basis for a future 1.0 release. Exactly when 1.0 is released depends on bugs reported (or lack thereof) and user feedback on the new features. So if you are using MacWire, please try updating and let us know if there are any problems!