Implementing the Inversion of Control Pattern in C#

In my previous post I spoke about the first principle of SOLID. In this post I explain last two principle. I hope it will be clear enough.

Dependency Inversion Principle (DIP)

Dependency Injection Principle states that there should be more abstraction between the higher level module and the lower level module. It is required to have loose coupling so that any change in the low level modules will not affect or there will be minimal impact at the higher level module. The ideal scenario would be when you write components for other applications to consume.

Inversion-of-Control-Pattern-1

In the example provided in Fig 1.0 VehicleController is the higher level module, which consumes and uses the lower level module Car. If you want to change the vehicle to Truck instead of Car then VehicleController does not require any change if there is higher level of abstraction.

Inversion of Control (IoC)

Inversion of Control is a technique to implement the Dependency Inversion Principle in C#. Inversion of control can be achieved by using interfaces or abstract class. The rule is that the lower level modules should sign up the contract to a single interface and the higher level module will consume only modules that are implementing the interface. This technique removes the dependency between the modules.

Inversion-of-Control-Pattern

As shown in Fig 2.0 Car and Truck will implement the interface IVehicle and VehicleController will couple with the vehicles through the IVehicle interface thus increasing the level of abstraction between the layers.

Sample IoC implementation in C#

In this section we will see the implementation of the IoC technique in the C# language. In Visual Studio create a Console application project and name it IoCDemo. Now add classes named VehicleController, Car, Truck and an interface IVehicle. In a real work scenario these items will be in separate layers like Car and Truck in one layer, IVehicle interface in abstraction layer and VehicleController as the higher level module. I have clubbed everything into a single project as it is a sample code. Following is the sample C# code implementing IoC.

public class Car : IVehicle
{

    #region IVehicle Members

    public void Accelerate()
    {
        Console.WriteLine("Car accelerates...");
    }

    public void Brake()
    {
        Console.WriteLine("Car stopped.");
    }

    #endregion
}

public class Truck : IVehicle
{
    #region IVehicle Members

    public void Accelerate()
    {
        Console.WriteLine("Truck accelerates...");
    }

    public void Brake()
    {
        Console.WriteLine("Truck stopped.");
    }

    #endregion
}

public interface IVehicle
{
    void Accelerate();
    void Brake();
}

public class VehicleController
{
    IVehicle m_Vehicle;

    public VehicleController(IVehicle vehicle)
    {
        this.m_Vehicle = vehicle;
    }

    public void Accelerate()
    {
        m_Vehicle.Accelerate();
    }

    public void Brake()
    {
        m_Vehicle.Brake();
    }
}

class Program
{
    static void Main(string[] args)
    {
        IVehicle vehicle = new Car();
        //IVehicle vehicle = new Truck();

        VehicleController vehicleController = new VehicleController(vehicle);
        vehicle.Accelerate();
        vehicle.Brake();

        Console.Read();
    }
}

In the above code the products are completely decoupled from the consumer using the IVehicle interface. The object is injected into the constructor of the VehicleController class in reference with the interface IVehicle. The constructor where the object gets injected is called as Injection Constructor.

Inversion of Control Container

If you look at the code sample provided in the above section, the Car or Truck object creation is still present in the Main method, which is again a dependency. In IoC technique the creation of the object will also be delegated to a separate component or framework, which will take care of creating and injecting the dependency object. This is called dependency injection and the component accomplishing the task is called the IoC container.

There are many IoC containers readily available in the market; some of the popular ones are the following.

  1. Microsoft Unity framework
  2. Castle Windsor
  3. NInject

You can also create your own custom IoC container using reflection and generics in C#. I hope this article has provided enough information about the Inversion of Control pattern.

Happy coding!

SOLID principles in C#

SOLID is an acronym and stands for 5 important object oriented principles. The SOLID principles help in making the object oriented application source code robust, scalable, extensible and non-fragile. It is absolutely necessary when you have a layered architecture and they are bound to changes over the period of time. Following are the 5 principles.

  1. Single Responsibility Principle
  2. Open Closed Principle
  3. Liskov Substitution Principle
  4. Interface Segregation Principle
  5. Dependency Inversion Principle

In this article I will take you through all three all five SOLID principles and also provide sample C# code to demonstrate them.

Single Responsibility Principle (SRP)

SRP states that every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class. There should only be a single reason for making the change to a class.

It means that a class should not be loaded with multiple responsibilities and a single responsibility should not be scattered across multiple classes and mixed with other responsibilities. The reason is that the more changes requested in the future, the more changes the class needs to undergo.

Below is a code violating the SRP. In the sample code, SRP is violated by mixing the OpenGate and CloseGate responsibility with the core vehicle service functionality.

public class ServiceStation
{
    public void OpenGate()
    {
        //Open the gate if the time is later than 9 AM
    }

    public void DoService(Vehicle vehicle)
    {
        //Check if service station is opened and then
        //complete the vehicle service
    }

    public void CloseGate()
    {
        //Close the gate if the time has crossed 6PM
    }
}

The re-factored code sample is as follows. A new interface is created and the gate related utility methods are moved to a different class called ServiceStationUtility.

public class ServiceStation
{
    IGateUtility _gateUtility;

    public ServiceStation(IGateUtility gateUtility)
    {
        this._gateUtility = gateUtility;
    }
    public void OpenForService()
    {
        _gateUtility.OpenGate();
    }

    public void DoService()
    {
        //Check if service station is opened and then
        //complete the vehicle service
    }

    public void CloseForDay()
    {
        _gateUtility.CloseGate();
    }
}

public class ServiceStationUtility : IGateUtility
{
    public void OpenGate()
    {
        //Open the shop if the time is later than 9 AM
    }

    public void CloseGate()
    {
        //Close the shop if the time has crossed 6PM
    }
}

public interface IGateUtility
{
    void OpenGate();
    void CloseGate();
}

Open Closed Principle (OCP)

OCP states that software application source codes should be open for extension but should be closed for modification.

According to the OCP principle the code should be easily extensible but it should not need any changes to be done to the core implementations. Following is a C# source code violating OCP where a new car has to be added then it will require changes in the core function CalculateMileage.

public class MileageCalculator
{
    IEnumerable<car> _cars;
    public MileageCalculator(IEnumerable<car> cars) { this._cars = cars; }

    public void CalculateMileage()
    {
        foreach (var car in _cars)
        {
            if (car.Name == "Audi")
                Console.WriteLine("Mileage of the car {0} is {1}", car.Name, "10M");
            else if (car.Name == "Mercedes")
                Console.WriteLine("Mileage of the car {0} is {1}", car.Name, "20M");
        }
    }
}

The OCP violation can be fixed as shown below, using an interface and creating classes for each car there, by reducing making the CalculateMileage method more generic and extensible.

public class MileageCalculator
{
    IEnumerable<car> _cars;
    public MileageCalculator(IEnumerable<car> cars) { this._cars = cars; }

    public void CalculateMileage()
    {
        CarController controller = new CarController();
        foreach (var car in _cars)
        {
            Console.WriteLine("Mileage of the car {0} is {1}", car.Name, controller.GetCarMileage(car.Name));
        }
    }
}

public class CarController
{
    List<icar> cars;
    public CarController()
    {
        cars = new List<icar>();
        cars.Add(new Audi());
        cars.Add(new Mercedes());
    }

    public string GetCarMileage(string name)
    {
        return cars.First(car => car.Name == name).GetMileage();
    }
}

public interface ICar
{
    string Name { get; set; }
    string GetMileage();
}

public class Audi : ICar
{
    public string Name { get; set; }

    public string GetMileage()
    {
        return "10M";
    }
}

public class Mercedes : ICar
{
    public string Name { get; set; }

    public string GetMileage()
    {
        return "20M";
    }
}

Liskov Substitution Principle (LSP)

LSP states that the derived classes should be perfectly substitutable for their base classes. If class D is derived from A then D should be substitutable for A.

Look at the following C# code sample where the LSP is broken. Simply, an Orange cannot substitute an Apple, which results in printing the color of apple as Orange.

namespace SolidDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Apple apple = new Orange();
            Console.WriteLine(apple.GetColor());
        }
    }

    public class Apple
    {
        public virtual string GetColor()
        {
            return "Red";
        }
    }

    public class Orange : Apple
    {
        public override string GetColor()
        {
            return "Orange";
        }
    }
}

Now let us re-factor and make it comply with LSP by having a generic base class for both Apple and Orange.

namespace SolidDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Fruit fruit = new Orange();
            Console.WriteLine(fruit.GetColor());
            fruit = new Apple();
            Console.WriteLine(fruit.GetColor());
        }
    }

    public abstract class Fruit
    {
        public abstract string GetColor();
    }

    public class Apple : Fruit
    {
        public override string GetColor()
        {
            return "Red";
        }
    }

    public class Orange : Apple
    {
        public override string GetColor()
        {
            return "Orange";
        }
    }
}

Interface Segregation Principle (ISP)

ISP states that no clients should be forced to implement methods which it does not use and the contracts should be broken down to thin ones.

Say for example when a thick interface is defined declaring a wide responsibility of members then there will be opportunities where some clients may have to implement members, which they don’t even use. In the below mentioned example ISP is violated where ProcessCreditCard method is not required by InpersonOrder class but is forced to implement.

public interface IOrder
{
    void Purchase();
    void ProcessCreditCard();
}

public class OnlineOrder : IOrder
{
    public void Purchase()
    {
        //Do purchase
    }

    public void ProcessCreditCard()
    {
        //process through credit card
    }
}

public class InpersionOrder : IOrder
{
    public void Purchase()
    {
        //Do purchase
    }

    public void ProcessCreditCard()
    {
        //Not required for inperson purchase
        throw new NotImplementedException();
    }
}

Now let us fix the violation by breaking down the IOrder interface.

public interface IOrder
{
    void Purchase();
}

public interface IOnlineOrder
{
    void ProcessCreditCard();
}

public class OnlineOrder : IOrder, IOnlineOrder
{
    public void Purchase()
    {
        //Do purchase
    }

    public void ProcessCreditCard()
    {
        //process through credit card
    }
}

public class InpersionOrder : IOrder
{
    public void Purchase()
    {
        //Do purchase
    }
}

Dependency Inversion Principle (DIP)

DIP states that the higher level modules should be coupled with the lower level modules with complete abstraction.

You can read more about DIP and IoC please check here.

Advertsing

125X125_06


Subscribe to our mailing list

* indicates required


TagCloud

MonthList

CommentList