1

I have the impression that Dependency Injection isn't friendly with immutability. I use Microsoft Dependency Injection but I am open to another one and I wanted to have fields / properties read only as much as possible, thus having a construction phase then the init phase it's the best solution. My problem occurred when I need to create a class with data fetched over the internet, I would like something like that:

var services = new ServiceCollection();
services.AddSingleton<IMyWebService, MyWebService>();
services.AddSingleton<IMyOtherService, MyOtherService>(async sp =>
   {
       var webService = sp.GetService<IMyWebService>();
       return new MyOtherService(await webService.GetDataAsync());
   });

Making it synchronous will make my app non responsive.

Olivier D
  • 64
  • 4

1 Answers1

5

You can't do that. There was a question on dependency injection about just that here that quickly explains why not: https://github.com/simpleinjector/SimpleInjector/issues/243

The gist of it

injection constructors should be simple. Not only does this hold for injection constructors, but in fact this advice should be applied to the whole graph. Creation of the graph should be fast and reliable. Doing I/O not only makes it slow, but allows the graph to fail for a different reason than being wired incorrectly, and it makes it very hard to verify and diagnose the graph without the availability of this external system (in your case the database).

You can pass the service to your object though and get the data there. How would this violate immutability?

Pass the reference and allow your class to only set the data once. You've got encapsulation to help you with that.

Athanasios Kataras
  • 25,191
  • 4
  • 32
  • 61
  • Agreed. This seems like a bad idea. – Jonesopolis Oct 05 '20 at 15:11
  • I don't see how to do that, make have a nullable field for the data and do a null check every time? On the init only set the value if the data field is null? – Olivier D Oct 05 '20 at 15:36
  • You should [prevent injecting runtime data into DI components](https://blogs.cuttingedge.it/steven/p/runtime-data/). That elegantly solves your problem. – Steven Oct 05 '20 at 16:21
  • @Steven Even tho the article is interesting, it doesn't solve the async problem. – Olivier D Oct 05 '20 at 16:37
  • See: https://stackoverflow.com/questions/32512266/how-to-perform-async-initalization-of-lazy-injection – Steven Oct 05 '20 at 16:40
  • And see: https://stackoverflow.com/questions/45924027/avoiding-all-di-antipatterns-for-types-requiring-asynchronous-initialization – Steven Oct 05 '20 at 16:40
  • @Steven Thanks, I end up using Stephen Cleary's AsyncLazy. – Olivier D Oct 05 '20 at 19:20