Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to implement dependency injection without using service locator at the start of an application?

I am fairly familiar with concepts of service locator and dependency injection, but there is one thing that gets me confused all the time, i.e., to implement dependency injection for an application we must use some sort of service locator at the start. Please consider the following code,lets say we have some simple DAL class:

public class UserProviderSimple : IUserProvider
{
    public void CreateUser(User user)
    {
        //some code to user here
    }
}

And then in the Business Logig Layer we have some simple class that uses IUserProvider that is injected using constructor injection:

public class UserServiceSimple : IUserService
{
    public IUserProvider UserProvider { get; set; }
    public UserServiceSimple(IUserProvider userProvider)
    {
        UserProvider = userProvider;
    }
    public void CreateUser(User user)
    {
        UserProvider.CreateUser(user);
    }
}

Now we may have couple of classes like that and use constructor injection everywhere, but in the main class where the application starts, all these types have to be resolved anyway, hence we must use a service locator to resolve all these types, for example, here I will create a singleton service locator class to resolve all the dependencies at the start of a console application like this:

public class ServiceLocator
    {
        private readonly UnityContainer _container;

        private static ServiceLocator _instance;

        public static ServiceLocator Instance()
        {
            if (_instance == null)
            {
                _instance = new ServiceLocator();
                return _instance;
            }
            return _instance;
        }

        private ServiceLocator()
        {
            _container = new UnityContainer();
            _container.RegisterType<IUserProvider, UserProviderSimple>();
            _container.RegisterType<IUserService, UserServiceSimple>();
        }

        public T Resolve<T>()
        {
            return _container.Resolve<T>();
        }
    }
    class Program
    {
        private static IUserService _userService;
        private static void ConfigureDependencies()
        {
            _userService = ServiceLocator.Instance().Resolve<IUserService();
        }

        static void Main(string[] args)
        {
            ConfigureDependencies();
        }
    }

So it seems like some kind of service locator is always used at the start of the application, hence using service locator is inevitable and it's not correct to always call it an anti-patern right (unless it's used not in the root of the application)?

like image 582
Mykhailo Seniutovych Avatar asked Apr 28 '17 09:04

Mykhailo Seniutovych


1 Answers

You misunderstand what a Service Locator is. You do understand the part that it is an anti-pattern, which is good, but what you're missing is that the pattern is not about the mechanics, but the role it plays in the application. In other words:

A DI container encapsulated in a Composition Root is not a Service Locator - it's an infrastructure component.

like image 137
Steven Avatar answered Sep 18 '22 13:09

Steven