Dependency injection and service locator

To download Dependency Injection source code example, click here

Dependency injection is a interface programing technique which is based on altering class behavior without the changing the class internals. That’s been done by coding against interface inside of the class and exposing interface definition to code external to the component. There are three types (different techniques) of making dependency injection: constructor DI, setter DI and interface DI.

Service locator is a design pattern similar to dependency injection in a meaning that allows altering the class behavior without altering the class code by coding against the interface inside of the class. The difference is that there’s no direct exposure of interface to code outside of the class. Instead class is using “well known object” inside, to get from it desired interface implementation.

This helper well known object can be 3pt framework such as Structure Map or to build the framework by ourselves

Use case

The example I’ll be using here is a kind of paycheck application which should write appropriate worker checks with appropriate amounts and title. Currently, there are two types of workers: Developer and Program manager, but in the future there could be some more. Developer has salary of $100 and the program manager has 3x bigger salary (like in real world, isn’t it? 🙂 )

The task is to make a paycheck application which would without the changing of the app code allow printing the paychecks for the different type of workers

Common implementation

There would be an IWorker interface defined like:

    public interface IWorker
    {
        string Name { get; set;}
        string SurName { get; set;}
        string Occupation { get;}
        decimal Salary { get;}
    }

And that interface would be implemented by Developer and ProjectManager classes

Developer class

public class Developer : IWorker
{
        public Developer(string name, string surname)
        {
            _name = name;
            _surname = surname;
        }

        #region IWorker Members

        private string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        private string _surname;
        public string SurName
        {
            get { return _surname; }
            set { _surname = value; }
        }

        public string Occupation
        {
            get { return “Developer”; }
        }

        public decimal Salary
        {
            get { return HelperMethods.GetSalary(TypeOfWorker.Developer); }
        }

}

Worker class

public class ProjectManager:IWorker
    {
        public ProjectManager(string name, string surname)
        {
            _name = name;
            _surname = surname;
        }

        #region IWorker Members

        private string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        private string _surname;
        public string SurName
        {
            get { return _surname; }
            set { _surname = value; }
        }

        public string Occupation
        {
            get { return “Project manager”; }
        }

        public decimal Salary
        {
            get { return HelperMethods.GetSalary(TypeOfWorker.ProjectManager); }
        }

        #endregion
    }

Both of classes, Developer and Manager for calculation of the Salary would use a helper method class GetSalaryMethod

public class HelperMethods
{
        public static decimal GetSalary(TypeOfWorker typeOfWorker)
        {
            decimal baseSalary = 100;
            if (typeOfWorker==TypeOfWorker.ProjectManager)
            {
                baseSalary = baseSalary*3;
// 🙂
            }
            return baseSalary;
        }
}

Our little class which would print the paychecks would be called PayCheck and it would have a void method PrintTheSalary()

Dependency injection – Constructor type

Constructor type dependency injection is based on a approach where the interface parameter which is referenced internally inside the class is been exposed through the constructor. In our example, class PayCheck would have a constructor which would have an IWorker parameter.

Implementation :

public class PayCheckCtor
{
      private IWorker _worker;

       public PayCheckCtor(IWorker worker)
        {
            _worker = worker;
        }

        public void PrintTheSalary()
        {
            Console.WriteLine(
                string.Format(“Name:{0}, Surname: {1}, Title: {2}, Salary:{3}”, _worker.Name,
               _worker.SurName, _worker.Occupation, _worker.Salary));
        }
}

Usage:

Developer developer = new Developer(“Nikola”, “Malovic”);
ProjectManager manager = new ProjectManager(“John”, “Doe”);

PayCheckCtor payCheck;
           
payCheck = new PayCheckCtor(developer);
payCheck.PrintTheSalary();

payCheck = new PayCheckCtor(manager);
payCheck.PrintTheSalary();

The good side of this approach is that in the moment when the code inside of the PayCheck class accessing the interface property, that property is guarantee to be initialized. The down side is that once injected value of the Interface can not be altered during the life time of the implementation (PayCheck)class  after the instance is been constructed.

Dependency injection – Setter type

Setter type of the DI pattern is enabling the injection of the interface implementation through the public property with set block. It is basically approach trying to cover the downsides of constructor based approach,

Implementation

public class PayCheckSet
{
        private IWorker _worker;
        public IWorker worker
        {
            set { _worker = value; }
        }

        public void PrintTheSalary()
        {
            Console.WriteLine(
                string.Format(“Name:{0}, Surname: {1}, Title: {2}, Salary:{3}”, _worker.Name,
                _worker.SurName, _worker.Occupation, _worker.Salary));
        }
}

Usage

Developer developer = new Developer(“Nikola”, “Malovic”);
ProjectManager manager = new ProjectManager(“John”, “Doe”);
PayCheckSet payCheck = new PayCheckSet();

payCheck.worker = developer;
payCheck.PrintTheSalary();
           
payCheck.worker = manager;
payCheck.PrintTheSalary();

The good side in this approach is that  it allows flexible changing of the interface implementation (on the fly). The down side is that when the code inside the class uses interface field, it is not guaranteed that the field wouldn’t be null

Dependency injection – Interface type

Is a dependency injection technique which is a kind of explicit defined setter type DI. The object which would use the interface property has to support interface which defines the method which sets the interface property

Implementation

There would be an interface which defines setting of the interface property value

public interface ISetWorker
{
            void SetWorker(IWorker worker);
}

Implementation class (PayCheck) would have then to implement that interface

public class PayCheckIntf : ISetWorker
{
        private IWorker _worker;

        public void SetWorker(IWorker worker)
        {
            _worker = worker;
        }
       
        public void PrintTheSalary()
        {
            Console.WriteLine(
                string.Format(“Name:{0}, Surname: {1}, Title: {2}, Salary:{3}”, _worker.Name,
               _worker.SurName, _worker.Occupation, _worker.Salary));
        }
}

Usage

Developer developer = new Developer(“Nikola”, “Malovic”);
ProjectManager manager = new ProjectManager(“John”, “Doe”);

PayCheckIntf
payCheck = new PayCheckIntf();

payCheck.SetWorker(developer);
payCheck.PrintTheSalary();

payCheck.SetWorker(manager);
payCheck.PrintTheSalary();

Service locator

For all three explained dependency injection techniques the common is the fact that they are ignorant completely about where from implementation of the interface comes and when it would be initialized.

Service locator is also a dependency injection technique, but the decision about the way and moment of the implementation is moved to the implementation class itself (instead of outside interface implementation definition)

It could be even said that it is more  Dependency Absorption rather Dependency Injection 🙂

Implementation

Service locator is usually either 3pt framework or our special assembly, which can decide about the type of interface implementation based on some configuration settings or something similar. Basically the whole point in using service locator is to extract and abstract the interface implementation decision outside of the implementation class. It is not a good practice that the implementation class is calling the Service Locator method by providing some method (like a Factory does) because implementation class should be ignorant about the Service Locator implementation.

In this example, Service locator implementation uses Singleton with GetWorker and RegisterWorker methods

I didn’t want to implement it fully with configuration settings of desired implementation, because it would introduce unnecessary complexity to sample.

public class WorkersServiceLocator
    {
        private static IWorker _worker;

        public static IWorker GetWorker()
        {
            return _worker;
        }

        public static void RegisterWorker(IWorker worker)
        {
            _worker = worker;
        }
    }

The PayCheck implementation using that ServiceLocator

public class PayCheckServLocator
    {
        public void PrintTheSalary()
        {
            ServiceLocator.IWorker _worker
                =ServiceLocator.WorkersServiceLocator.GetWorker();
            Console.WriteLine(
                string.Format(“Name:{0}, Surname: {1}, Title: {2}, Salary:{3}”, _worker.Name,
                _worker.SurName,  _worker.Occupation, _worker.Salary));
        }
    }

Usage

Developer developer = new Developer(“Nikola”, “Malovic”);
ProjectManager manager = new ProjectManager(“John”, “Doe”);

PayCheckServLocator payCheck = new PayCheckServLocator();

WorkersServiceLocator.RegisterWorker(developer);
payCheck.PrintTheSalary();

WorkersServiceLocator.RegisterWorker(manager);
payCheck.PrintTheSalary();

The good side in this approach is that  the control is allowed to control the moment of interface variable definition. It still allows flexible changing of the interface implementation because the service location internals are abstracted from  the implementing class level. The down side is that the implementation class is not so dumb any more and it has to take care about things outside of her scope (call to ServiceLocator method)

Conclusion:

Dependency injection is a very powerful technique very much used in Test Driven Development and I would speak more in near future about it in posts about TDD

 

Advertisements

Posted on January 19, 2007, in Uncategorized. Bookmark the permalink. 5 Comments.

  1. Thanks for this explanation. It is very usefull for me. I needed some easy to understand explanation for my

  2. I’ve just blog posted another blog post touching the same subject (Service locator vs. Dependency injection) from a different and a little bit more advanced angle
    blog.vuscode.com/…/dependency-injection-in-real-world.aspx

  3. This was a good article all the way up until you said, "Service Locator is a dependency injection technique".
    DI is a pattern like SL. However, DI is a pattern to achieve IoC. The roots of IoC is changing who is in control. A component that internally resolves it’s own dependencies is in control (SL style). This is the traditional way. A component that is given dependencies is NOT in control (DI style). This is IoC in the context of dependency resolution.  
    DI achieves IoC, SL does not.

  4. Json,
    you are right from pattern point of view but…
    Applying DI without the help of IoC container is quite an overkill and lead to broken encapsulation and if you think about DI in context of IoC containers you would see that each one of the IoC containers performing DI (Unity, StructureMap, Windsor, Ninject etc) have allways a ServiceLocator class which you use to register, retrieve your services.
    IMHO, In that context SL could be called as a technique of performing DI altought I am aware it is Fowler POEA pattern
    Please check out some of my more recent post presenting my views on the necessity of SL in big corps
    blog.vuscode.com/…/dependency-injection-in-real-world.aspx

  5. Hi, very interesting article. Simple and easy to understand.
    I have one question, what is the difference between the Factory and Service Locator?
    Thanks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: