Adam Warski

22 Jul 2014

MacWire 0.7: dynamically accessing the object graph

dependency injection
macwire
modularity
scala

MacWire is a Lightweight and Nonintrusive Scala Dependency Injection library.

While it would be great to be able to define in a type-safe way the whole object graph for an application upfront, there are cases when it is necessary to access and extend it dynamically. That’s why MacWire 0.7 contains new API and functionality for that purpose.

First use-case is when integrating with web frameworks, such as Play 2. There it is often needed to access a wired instance by-class. Such functionality was available in MacWire before (with instance maps), however using it was cumbersome. For a full example, see the Play-MacWire activator.

Second use-case is dynamically creating instances of classes, which names are only known at run-time, such as plugins. It is now possible to instantiate such classes, using the dependencies defined in a module.

Both of these use-cases can be realised by the Wired class, which can be created given an instance of a module, containing the object graph, using the wiredInModule macro. Any vals, lazy vals and parameter-less defs will be available. An instance of Wired can be also extended with new instances and instance factories.

For example:

// 1. Defining the object graph and the module
class SecurityFilter

trait DatabaseConnector
class MysqlDatabaseConnector extends DatabaseConnector

class MyApp {
    def securityFilter = new SecurityFilter()
    val databaseConnector = new MysqlDatabaseConnector()
}

// 2. Creating a Wired instance
import MacwireMacros._
val wired = wiredInModule(new MyApp)

// 3. Dynamic lookup of instances
wired.lookup(classOf[SecurityFilter])

// Returns the mysql database connector, even though its type is 
// MysqlDatabaseConnector, which is assignable to DatabaseConnector.
wired.lookup(classOf[DatabaseConnector])

// 4. Instantiation using the available dependencies
{
    package com.softwaremill
    class AuthenticationPlugin(databaseConnector: DatabaseConnector)
}

// Creates a new instance of the given class using the dependencies 
// available in MyApp
wired.wireClassInstanceByName("com.softwaremill.AuthenticationPlugin")

Also, if you are an existing or future user of MacWire, remember to +1 the features you’d like to see implemented.

comments powered by Disqus

Any questions?

Can’t find the answer you’re looking for?