Introduction to SIOC
This article is a short intoduction to the SIOC Inversion of Control framework.
What is Inversion of Control
Inversion of Control (IoC), also known as Dependency Injection (DI) is an approach to application design where you do not create your objects.
So how do you create objects. With IoC you describe an object in a configuration file and request the object from an IoC container (an implementation of the factory pattern).
There are several implementation methods for IoC containers:
-
Constructor injection: An object is supplied with its dependencies via constructor arguments.
-
Setter injection: After an object is constructed it is supplied with its dependencies via setters
-
Interface based: An interface will define the injection method and an implementation of the interface will provide the injection mechanism.
In this article we will be using SIOC a C# IoC framework which uses setter injection.
The Example
As an example, when using the a layered design you could implement your code as shown in the following snippet.
class Layer2
{
public void Process()
{
Console.WriteLine( "Layer2 Process" );
}
}
class Layer1
{
Layer2 layer2;
public Layer1()
{
layer2 = new Layer2();
}
public void Process()
{
Console.WriteLine( "Layer1 Process" );
layer2.Process();
}
}
class Program
{
static void Main( String[] args )
{
Layer1 l1 = new Layer1();
l1.Process();
}
}
If we run the application we will see the following output:
Layer1 Process
Layer2 Process
When using IoC you do not directly connect components together within your application. A configuration file describes which components use the services of other components and how they relate to each other. When you ask for a component the container takes care of the object creation including the connecting of components together. We will now convert the example to use IoC.
The first step is to create the SIOC configuration file.
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns:articlens="SiocArticle, SiocArticle">
<object id="Layer1" type="articlens:Layer1" />
</objects>
Here we have defined a single object named 'Layer1' in the namespace SiocArticle and the assembly SiocArticle.
In order to create the object we have to load the configuration into the SIOC framework, then request the Layer1 object from the framework. We modify the main application code as follows:
class Program
{
static void Main( string[] args )
{
ISiocContext defaultCtx = SiocContext.GetContext();
defaultCtx.LoadObjects( "file://accu.xml" );
Layer1 l1 = SiocClassFactory;( "layer1" );
l1.Process();
}
}
If we run the programe again we will see the same results as before. Now we are using the IoC framework as a factory to create an object named 'layer1' of the type 'Layer1'. The next step is to make it all more interesting. We will now remove the creation of the Layer2 object in the Layer1 constructor. First we must modify the configuration file.
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns:articlens="SiocArticle, SiocArticle">
<object id="layer1" type="articlens:Layer1">
<property name="SetLayer2" ref="layer2"/>
</object>
<object id="layer2" type="articlens:Layer2" />
</objects>
The configuration has a second object, layer2. We have also defined a property on the layer1 object called 'SetLayer2' that has a reference to the configuration object 'layer2'. We must also modify the Layer1 class to reflect these changes.
class Layer1
{
Layer2 layer2;
public Layer2 SetLayer2
{
set { layer2 = value; }
}
public void Process()
{
Console.WriteLine( "Layer1 Process" );
layer2.Process();
}
}
Now when we ask the IoC factory for the layer1 object, it will return it with the layer2 object set. If we run the application again we see the output:
Layer1 Process
Layer2 Process
What are the advantages of using IoC:
-
Promotes loose coupling between components. Code to an interface not an implementation.
-
The ability to easily test components. Using setter injection it is easy to inject mock objects into a component under test, unit testing and test driven development can be implemented much easier.
-
Application configuration. By making changes to a configuration file new versions of components can be injected into the application.
What services does the SIOC IoC framework provide:
-
Multiple contexts allowing a seperation of concerns within an application.
-
Ability to call an initialize function after object creation.
-
Setting of properties using system types. String, int, enum etc.
-
Setting collections. i.e. A list of currencies.
-
Setting maps. i.e. Mapping currency to a country.
-
Singletons: Created after the configuration is loaded.
-
Events: The framework implements loosly coupled events. This enables subscribers to register for events before publishers have been created.
SIOC currently has 135 unit tests covering 94% of the code base.