simpleinjector / SimpleInjector

An easy, flexible, and fast Dependency Injection library that promotes best practice to steer developers towards the pit of success.
https://simpleinjector.org
MIT License
1.21k stars 155 forks source link

Any drawbacks accessing the container in large scale, temporally, with GetInstance during project migration ? #959

Closed rfbortolini closed 1 year ago

rfbortolini commented 1 year ago

We are preparing to migrate a huge project of hundreds / thousands of classes to use Dependency Injection and Simple Injector.

Nowadays, classes are instantiated with regular "new" pattern, as the example bellow.

public class ClassA {

   public ClassA(){}

  public MethodA() {
     var classB = new ClassB();
     classB.MethodB();
  }
}

public class ClassB {

   public ClassB(){}

  public MethodB() {
     var classC = new ClassC();
  }
}

To gradually migrate classes to use DI, as several are interconnected, we are considering not using the auto wiring feature and constructor resources at the first moment. Change the constructor would mean change all interconnected classes up.

So we are thinking to access the container directly in the constructor

public class ClassA {

   private readonly IClassB _classB;

   public ClassA(){
        _classB = Container.GetInstance<IClassB>();
   }

  public MethodA() {
     _classB.MethodB();
  }
}

public class ClassB {

   private readonly IClassC _classC;

   public ClassB(){
        _classC = Container.GetInstance<IClassC>();
  }

  public MethodB() {
     _classC.MethodB();
  }
}

At the second moment, when everything is migrated, we would implement auto wiring and instantiate everything in the constructor with auto wiring.

1 - Is this a good strategy? 2 - Are there any possible drawbacks of accessing the container directly this way? 3 - Any possible performance issues?

Thanks a lot!

dotnetjunkie commented 1 year ago

Is this a good strategy?

This is a hard-to-answer question. In general, I would say that when it comes to refactoring a legacy code base to something more maintainable, every method that allows you to gradually get out of that place is a valid approach. This even includes the Service Locator anti-pattern, which is what you are proposing.

Still, I'd typically prefer applying DI in small steps at a time. This means that you apply constructor injection (and use the container's auto-wiring abilities) for a few (cleverly chosen) classes at the time. I would rather prefer that option over practicing the Service Locator anti-pattern, because of all the downsides that this pattern brings with it.

Are there any possible drawbacks of accessing the container directly this way?

Absolutely. Read this or -even better- the complete section in my book DIPP&P.

Any possible performance issues?

I would say that Simple Injector is optimized enough to not notice very much of this, but still, the performance of using a Container as a Service Locator can be much slower compared to pulling in a complete object graph at once. Especially with Simple Injector, which is very optimized for the auto-wiring scenario. You'll find that this is much more performant compared to calling back into the Container from within application code.

rfbortolini commented 1 year ago

Thanks a lot for your very helpful answer!