【WPF 依赖注入】WPF 依赖倒置 应用案例 -CommunityToolkit.Mvvm.DependencyInjection
实现控制反转的前提是依赖倒置
环境
.net6+vs2022+CommunityToolkit.Mvvm框架
using CommunityToolkit.Mvvm.DependencyInjection;mvvm框架的内置的依赖注入模块。
在服务容器中注册依赖关系。 .NET6提供了一个内置的服务容器 IServiceProvider。将服务注入到使用它的类的构造函数中。 框架负责创建依赖关系的实例,并在不再需要时将其释放。
案例项目
注册服务
在App.xam.cs中配置依赖注入。ServiceCollection 是容器 ,它的生命周期必须要跟我们应用程序同步,所以需要在应用程序初始化的时候,这个ioc 容器也要初始化
using CTMvvmDemo.MVVM.Views; using CTMvvmDemo.MVVM.ViewsModels; using CTMvvmDemo.Respositoies; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.Linq; using System.Threading.Tasks; using System.Windows; namespace CTMvvmDemo { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : Application { public App() { Services = ConfigureServices(); } /// <summary> /// 设置应用程序的启动界面 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void App_Startup(object sender, StartupEventArgs e) { MainWindowView window = new MainWindowView(); window.Show(); } /// <summary> /// Gets the current <see cref="App"/> instance in use /// </summary> public new static App Current => (App)Application.Current; /// <summary> /// Gets the <see cref="IServiceProvider"/> instance to resolve application services. /// </summary> public IServiceProvider Services { get; } /// <summary> /// 注册服务 /// ServiceCollection 是容器 ,它的生命周期必须要跟我们应用程序同步,所以需要在应用程序初始化的时候,这个ioc 容器也要初始化 /// </summary>//// /// private static IServiceProvider ConfigureServices() { //Fluent API 方式实现 注册服务;ServiceCollection是.net6自带的服务器容器 var services = new ServiceCollection() .AddSingleton<IStudentRespository, StudentRespository>() .AddSingleton<MainWindowViewModel>(); //注入实例 /* * 和Fluent API是等同的 var services = new ServiceCollection(); services.AddSingleton<IStudentRespository, StudentRespository>(); //注入实例 services.AddSingleton<MainWindowViewModel>(); */ return services.BuildServiceProvider(); } } }
知识点
服务生命周期
在Microsoft依赖项注入框架中,我们可以使用三种生命周期注册服务,分别是单例(Singleton)、瞬时(Transient)、作用域(Scoped),在上面的代码中,使用了AddSingleton()来注册服务。
使用Singleton服务的优点是我们不会创建多个服务实例,只会创建一个实例,保存到DI容器中,直到程序退出,这不仅效率高,而且性能高,但是有一个要注意的点,如果在多线程中使用了Singleton,要考虑线程安全的问题,保证它不会有冲突
瞬时(Transient)和单例(Singleton)模式是相反的,每次使用时,DI容器都是创建一个新的实例。
作用域(Scoped),在一个作用域内,会使用同一个实例,像EF Core的DbContext上下文就被注册为作用域服务。
给接口注入实例
应用依赖注入 MainWindowViewModel.cs类中应用public sealed partial class MainWindowViewModel:ViewModelBase { //其他代码 private IStudentRespository IstudentRespository; public MainWindowViewModel() { //依赖注入 ! 表示知道不会返回null 忽略警告 它的主要作用就是告诉编译器,变量不可能为 null this.IstudentRespository = App.Current.Services.GetService<IStudentRespository>()!; } //其他代码 }
注入实例
在MainWindowView.xaml.cs类中 应用实例注入
using CTMvvmDemo.MVVM.ViewsModels; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; namespace CTMvvmDemo.MVVM.Views { /// <summary> /// Window1.xaml 的交互逻辑 /// </summary> public partial class MainWindowView : Window { public MainWindowView() { InitializeComponent(); //依赖注入 this.DataContext = App.Current.Services.GetService(typeof(MainWindowViewModel)); // this.DataContext = new MainWindowViewModel(); } } }
编程是个人爱好