Dependency Injection in C++ isn’t possible?

Starting up a new project called Cube a Libre I was confronted with no cool dependency injection framework in C++ like the famous Spring Framework in Java. I tested some of them: pococapsule, autumnframework and qtioccontainer. No one was acceptable (dependency to java(!), 6 years old, too complicated.

So I started a new experiment: Is Dependency Injection in C++ possible?

Yes and no. No, because there is no introspection. Yes, if you had a little help from the Qt framework which provides the metaobject system and a preprocessor called moc. So your project has the dependency to Qt. Also your classes can’t be implemented as plain old POJOs POCOs. They has to inherit from QObject. In addition, they has to implement some methods and has to register themselfs.

Lets take a look into the xml file:

 XML |  copy code |? 
01
<objects>
02
  <object name="scriptingManager" class="ScriptingManager" />
03
  <object name="pythonInterpreter" class="PythonInterpreter" />
04
  <object class="NetworkManager" init-method="init">
05
    <property name="pythonInterpreter" ref="pythonInterpreter" />
06
    <property name="startupScriptFilename" value="../engine/alive.py" />
07
  </object>
08
  <object name="jabberClient" class="JabberClient" destroy-method="destroy">
09
    <property name="name" value="**********" />
10
    <property name="password" value="**********" />
11
    <property name="server" value="**********" />
12
    <property name="resource" value="cube-a-libre" />
13
  </object>
14
</objects>

This looks much like a xml file you would use in Java/Spring. You can define objects from a classname (a string!), give them names, sets properties and inject other objects using the ref attribute.

Now lets take a look on a class definition:

 C++ (Qt) |  copy code |? 
01
class JabberClient : public QObject
02
{
03
    // For Qt Meta system
04
    Q_OBJECT
05
 
06
    Q_PROPERTY(QString name WRITE setName)
07
    Q_PROPERTY(QString password WRITE setPassword)
08
    Q_PROPERTY(QString server WRITE setServer)
09
    Q_PROPERTY(QString resource WRITE setResource)
10
 
11
    public:
12
        JabberClient();
13
        JabberClient(const JabberClient& jabberClient) {};
14
        virtual ~JabberClient();
15
 
16
        void connect();
17
        void disconnect();
18
        void sendMessage(QString jid, QString text);
19
 
20
        void onConnect(void);
21
 
22
        void setName(QString name);
23
        void setPassword(QString name);
24
        void setServer(QString server);
25
        void setResource(QString resource);
26
 
27
    public slots:
28
        void init();
29
        void destroy();
30
 
31
    private:
32
        QString name;
33
        QString password;
34
        QString server;
35
        QString resource;
36
};
37
 
38
REGISTER_CLASS(namespace::JabberClient, JabberClient);
39
 
40
Q_DECLARE_METATYPE(namespace::JabberClient*)
41

You can see, we need a constructor, a destructor and a copy constructor. The copy constructor doesn’t have to be implemented, but must exist. The class itself inherits from QObject, so we can use the Qt meta object system. Also we define the some properties and their setters. Using Qt’s PROPERTY macro we make the meta object system know them. At the bottom we can see, that we register the metatype using Q_DECLARE_METATYPE. Also, we register the class using the macro REGISTER_CLASS provided by cube-a-libre.

Finally we have to initialize the application context:

 C++ (Qt) |  copy code |? 
1
engine::XmlApplicationContext context;
2
context.createContextFromXmlFile("context.xml");
3
engine::JabberClient* jabberClient = (engine::JabberClient*) context.getObject("jabberClient");
4
jabberClient->init();
5
 
6
[...] more code [...]
7
 
8
context.destroyContext();

First, we create a XmlApplicationContext object. Then we let it create an application context from a xml file. The application context will be automagically created. Then we can make use of the getObject Method to get the singleton object instance. Finally, we destroy the context.