3

I am struggling on what makes the ServiceLocator an anti-pattern.

Some say, that passing the container around qualifies it as an antipattern, others fear the maintainability once the app grows (hidden dependencies). The following sample demonstrates a simple registration with AutoFac including dependencies:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AutoFacSample
{
    using System.Reflection;
    using Autofac;    

    class Program
    {
        static void Main(string[] args)
        {
            var assembly = Assembly.GetExecutingAssembly();
            var builder = new ContainerBuilder();
            builder.RegisterAssemblyTypes(assembly).Where(t => t.Name.Contains("First")).AsImplementedInterfaces();            
            Holder.Container = builder.Build();
            var first = Holder.Container.Resolve<IFirst>();
        }
    }

   public static class Holder
    {
        public static IContainer Container { get; set; }
    }

   public interface IFirst {}

   public interface ISecond {}

   public interface IThird {}

   public class First : IFirst
    {
        public First(ISecond second)
        {        
        }
    }

   public class Second : ISecond
    {
        public void Foo()
        {
            var third = Holder.Container.Resolve<IThird>();            
        }
    }

    public class Third : IThird {}    

}

Would you consider my sample as an anti-pattern? If so, is there any good alternative?

EDIT:
I'm aware of the question Is ServiceLocator an anti-pattern? but the answer doesn't explain weather my sample is an anti-pattern or not.

Thanks,

Trini

Trinitrotoluol
  • 205
  • 1
  • 13
  • 3
    It just hides dependencies. For `First` it's immediately clear it depends on `ISecond` (because you pass it in constuctor). For `Second` you have no idea it depends on `IThird` unless you have access to source code. – Evk Oct 16 '17 at 11:44
  • 1
    You can read `Dependency Injection in Net` from Seemann. – cSteusloff Oct 16 '17 at 11:44
  • This anti-pattern also limits composability. What if you want to have two instances of `Second` and have each one of them talking to a different implementation of `IThird`? See this article for more details: http://criticalsoftwareblog.com/index.php/2015/10/25/object-composability-another-reason-why-the-service-locator-is-an-anti-pattern/ – Yacoub Massad Oct 16 '17 at 11:47
  • The alternative is to declare `IThird` in the constructor of `Second`, i.e., use constructor injection. – Yacoub Massad Oct 16 '17 at 11:48
  • I already read Seemann's blog post (http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/) which only tells me, that its bad using the servicelocator as it makes maintainability harder and the overall API usage. – Trinitrotoluol Oct 16 '17 at 12:00

0 Answers0