Every ASP.NET Core developer uses builder.Services.AddScoped<...>(), but few understand what happens inside the Inversion of Control (IoC) Container. To master C# architecture, you must understand how the container uses Reflection and Service Lifetimes to manage the memory and disposal of your entire application graph.
Choosing the wrong lifetime is the #1 cause of memory leaks and captive dependencies in production.
The container is essentially a giant Dictionary<Type, ServiceDescriptor>. When you ask for an IUserService, the container:
UserService).This happens when a Singleton service mistakenly tries to inject a Scoped service. Because the Singleton never dies, it "captures" the Scoped service, keeping it alive for the entire app life. This can lead to database connection leaks or stale user data appearing for the wrong person!
Q: "Why should we prefer Constructor Injection over the Service Locator pattern (`serviceProvider.GetService
Architect Answer: "Service Locator is considered an Anti-Pattern because it hides the dependencies of a class. When you use Constructor Injection, you are declaring: 'I cannot function without these 3 services.' This makes the code self-documenting and incredibly easy to Unit Test (you just pass mocks). If you use a Service Locator, the class 'lies' about its dependencies, hides its requirements inside method bodies, and becomes almost impossible to test without mocking the entire underlying .NET service provider architecture."