Summary
Highlights
Dependency injection (DI) is integrated into .NET Core, enabling reduced coupling, increased testability, and easier application upgrades. This video will cover configuring and using DI in .NET 6, exploring various scope types, the significance of interfaces, and dependency updates. The presenter, Tim Corey, offers C# learning resources including YouTube videos, podcasts, and courses.
The demonstration starts with creating a new ASP.NET Core Blazor Server project in Visual Studio. DI is automatically configured in ASP.NET Core projects but requires manual setup for console, WinForms, or WPF apps. The video proceeds with cleaning up the project by deleting boilerplate code, including the 'Data' folder, 'FetchData' page, and related lines in 'Program.cs'.
A 'DemoLogic' class is created with two random integer properties (Value1 and Value2) initialized in the constructor. The initial demonstration shows manual instantiation of 'DemoLogic' on the 'Index.razor' page, resulting in new random values every time the page is accessed. This highlights tight coupling and the difficulty of swapping implementations without DI.
To implement DI, 'DemoLogic' is registered as a service in 'Program.cs' using 'builder.Services.AddTransient<DemoLogic>()'. On the 'Index.razor' page, the 'DemoLogic' instance is injected using '@inject DemoLogic Logic' instead of manual instantiation. 'AddTransient' ensures a new instance of 'DemoLogic' is provided every time it's requested, demonstrating the basic functionality of DI.
The 'AddSingleton' scope is introduced, providing a single instance of a class for the entire application lifetime. Changing 'AddTransient' to 'AddSingleton' in 'Program.cs' results in the same 'DemoLogic' values across all page loads and even different browser tabs, demonstrating a shared, long-lived instance. The presenter warns against overuse of singletons due to potential data sharing issues and memory usage.
The 'AddScoped' scope is explained as a middle ground, providing a single instance per client connection (e.g., per browser tab for web applications). 'AddScoped' allows for user-specific instances while maintaining consistency within that user's session. This is more relevant for web applications where multiple users can connect to the same server, unlike desktop applications.
The video emphasizes the importance of using interfaces with DI. An 'IDemoLogic' interface is extracted from 'DemoLogic' and registered as an 'AddTransient<IDemoLogic, DemoLogic>()'. This allows the 'Index.razor' page to depend on the interface ('@inject IDemoLogic Logic'), promoting loose coupling. This setup facilitates unit testing and easy swapping of implementations.
A 'BetterDemoLogic' class is created, also implementing 'IDemoLogic' but providing fixed values (25 and 50) instead of random ones. The demonstration shows how easily the application's behavior can be changed by modifying a single line in 'Program.cs' to 'builder.Services.AddTransient<IDemoLogic, BetterDemoLogic>()'. This highlights DI's power in managing and upgrading dependencies.
A practical example using logging is presented. The existing 'ILogger' interface is utilized, which is already configured in .NET Core via DI. The presenter then integrates 'Serilog' by adding its NuGet package and configuring it in 'Program.cs' using 'builder.Host.UseSerilog()'. The application automatically switches to Serilog's structured logging without any changes to the 'Index.razor' page, showcasing the flexibility of DI.
The video delves into deeper aspects of DI. It discusses how centralizing dependencies in 'Program.cs' fosters a conscious understanding of application dependencies. It addresses the common question of handling multiple implementations of the same interface, recommending against it as a general practice and suggesting alternative interface designs. The presenter also clarifies that models (data structures) should not be registered with DI.
The video concludes by summarizing the benefits of dependency injection in .NET Core (or .NET 5+). It reiterates that DI is built-in for web project types but requires setup for desktop and console apps. The speaker mentions that third-party DI containers like Autofac can replace Microsoft's default implementation for more advanced scenarios.