Dependency injection is the process of introducing a dynamic aspect to your program. Using an inversion of control process we can configure classes to be loaded at runtime and executed as a part of our process.
Let's look at an example program.
Diving into the configuration file we can tell we will be using three classes.
<Workflow>
<Step Run="ClassA" Return="ClassB"></Step>
<Step Run="ClassB" Return="ClassC"></Step>
<Step Run="ClassC"></Step>
</Workflow>
In order to use the injected classes we need to define interfaces. Interfaces help our IOC container dynamically invoke methods inside our classes
interface IClass
{
void MyMethod();
}
interface IResult
{
string MyResult();
}
Let’s define our classes
class ClassA : IClass, IResult
{
private string returnType = string.Empty;
public ClassA(string returnType)
{
this.returnType = returnType;
}
public void MyMethod()
{
Console.WriteLine("ClassA");
}
public string MyResult()
{
return returnType;
}
}
class ClassB : IClass, IResult
{
private string returnType = string.Empty;
public ClassB(string returnType)
{
this.returnType = returnType;
}
public ClassB()
{
}
public void MyMethod()
{
Console.WriteLine("ClassB");
}
public string MyResult()
{
return returnType;
}
}
class ClassC : IClass
{
public void MyMethod()
{
Console.WriteLine("ClassC");
}
}
The abstract factory in charge of creating the objects used by the IOC has two methods. One for creating objects with a default constructor and the other for objects that accept parameters.
static class ClassFactory
{
public static IClass GetClass(string className, string returnType)
{
return (IClass)Activator.CreateInstance(Type.GetType(Assembly.GetExecutingAssembly().GetTypes().Where(t=>t.Name.EndsWith(className)).FirstOrDefault().FullName), new object[] { returnType });
}
public static IClass GetReturnClass(string className)
{
return (IClass)Assembly.Load(Assembly.GetExecutingAssembly().FullName).CreateInstance(Assembly.GetExecutingAssembly().GetTypes().Where(t => t.Name.EndsWith(className)).FirstOrDefault().FullName);
}
}
The container itself is in charge of class invocation. The invocation is set by reading the configuration file, thus, injecting the dependency at runtime.
static void Main(string[] args)
{
XElement root = XElement.Load("Workflow.xml");
foreach (XElement element in root.Elements())
{
IClass myClass;
if(element.Attribute("Return")!=null)
myClass = ClassFactory.GetClass(element.Attribute("Run").Value, element.Attribute("Return").Value);
else
myClass = ClassFactory.GetReturnClass(element.Attribute("Run").Value);
myClass.MyMethod();
if (myClass is IResult)
{
IClass myResultClass = ClassFactory.GetReturnClass(((IResult)myClass).MyResult());
myResultClass.MyMethod();
}
}
Console.ReadLine();
}
The output will be:
ClassA
ClassB
ClassB
ClassC
ClassC

Posted
13 Nov 2009 8:04 AM
by
Gal Ratner