CommunityToolkit.Mvvm IOC 示例
这是一个专注于展示 CommunityToolkit.Mvvm IOC(依赖注入)功能的 WPF 示例项目。
项目结构
CommunityToolkit.Mvvm.IOC.Demo/
├── Services/
│ ├── IDataService.cs // 数据服务接口
│ ├── DataService.cs // 数据服务实现
│ ├── INotificationService.cs // 通知服务接口
│ └── NotificationService.cs // 通知服务实现
├── ViewModels/
│ └── MainViewModel.cs // 主视图模型
├── App.xaml // 应用程序资源
├── App.xaml.cs // 应用程序启动逻辑
├── MainWindow.xaml // 主窗口界面
└── MainWindow.xaml.cs // 主窗口代码
NuGet导入包
<ItemGroup><PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /><PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" /><PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /></ItemGroup>
项目完整代码
IDataService
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IocSample.Services
{public interface IDataService{List<string> GetUserNames();void AddUser(string name);}
}
DataService
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IocSample.Services
{public class DataService : IDataService{private readonly List<string> _users = new List<string>{"张三", "李四", "王五"};public List<string> GetUserNames(){return new List<string>(_users);}public void AddUser(string name){_users.Add(name);}}
}
INotificationService
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IocSample.Services
{public interface INotificationService{void ShowMessage(string message);}
}
NotificationService
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;namespace IocSample.Services
{internal class NotificationService : INotificationService{public void ShowMessage(string message){MessageBox.Show(message, "通知", MessageBoxButton.OK, MessageBoxImage.Information);}}
}
MainViewModel
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.DependencyInjection;
using IocSample.Services;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IocSample
{public partial class MainViewModel : ObservableObject{// 通过 IOC 容器获取服务实例private readonly IDataService _dataService;private readonly INotificationService _notificationService;[ObservableProperty]private string newUserName = "";[ObservableProperty]private ObservableCollection<string> users = new();// 构造函数注入依赖public MainViewModel(IDataService dataService, INotificationService notificationService){_dataService = dataService;_notificationService = notificationService;LoadUsers();}// 也可以通过 Ioc.Default 获取服务(服务定位器模式)public MainViewModel(){// 这种方式是通过服务定位器获取依赖_dataService = Ioc.Default.GetService<IDataService>();_notificationService = Ioc.Default.GetService<INotificationService>();LoadUsers();}private void LoadUsers(){var userList = _dataService.GetUserNames();Users.Clear();foreach (var user in userList){Users.Add(user);}}public void AddUser(){if (string.IsNullOrWhiteSpace(NewUserName)){_notificationService.ShowMessage("请输入用户名");return;}_dataService.AddUser(NewUserName);LoadUsers();_notificationService.ShowMessage($"用户 '{NewUserName}' 已添加");NewUserName = "";}public void RefreshUsers(){LoadUsers();_notificationService.ShowMessage("用户列表已刷新");}}
}
App.xaml.cs
using CommunityToolkit.Mvvm.DependencyInjection;
using IocSample.Services;
using Microsoft.Extensions.DependencyInjection;
using System.Configuration;
using System.Data;
using System.Windows;namespace IocSample
{/// <summary>/// Interaction logic for App.xaml/// </summary>public partial class App : Application{protected override void OnStartup(StartupEventArgs e){base.OnStartup(e);// 配置依赖注入容器ConfigureServices();}private void ConfigureServices(){// 创建服务集合var services = new ServiceCollection();// 注册服务services.AddSingleton<IDataService, DataService>();services.AddSingleton<INotificationService, NotificationService>();// 注册ViewModelservices.AddTransient<MainViewModel>();// 构建服务提供者并配置到 CommunityToolkit.Mvvm 的 IOC 容器var serviceProvider = services.BuildServiceProvider();Ioc.Default.ConfigureServices(serviceProvider);}}}
MainWindow.xaml
<Window x:Class="IocSample.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:IocSample"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Grid Margin="20"><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/><RowDefinition Height="*"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><!-- 标题 --><TextBlock Grid.Row="0" Text="用户管理系统" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center" Margin="0,0,0,20"/><!-- 添加用户区域 --><StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,0,0,20"><TextBox x:Name="txtNewUser" Text="{Binding NewUserName}" Width="200" Height="30" VerticalContentAlignment="Center"Margin="0,0,10,0"/><Button Content="添加用户" Width="80" Height="30" Click="AddUser_Click"/></StackPanel><!-- 用户列表 --><GroupBox Grid.Row="2" Header="用户列表" Margin="0,0,0,20"><ListBox x:Name="lstUsers" ItemsSource="{Binding Users}" FontSize="14" Padding="10"/></GroupBox><!-- 操作按钮 --><StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Center"><Button Content="刷新列表" Width="100" Height="35" Click="RefreshUsers_Click" Margin="0,0,10,0"/><Button Content="显示IOC信息" Width="100" Height="35" Click="ShowIocInfo_Click"/></StackPanel></Grid>
</Window>
MainWindow.xaml.cs
using CommunityToolkit.Mvvm.DependencyInjection;
using IocSample.Services;
using System.Text;
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.Navigation;
using System.Windows.Shapes;namespace IocSample
{/// <summary>/// Interaction logic for MainWindow.xaml/// </summary>public partial class MainWindow : Window{private readonly MainViewModel _viewModel;public MainWindow(){InitializeComponent();// 从 IOC 容器获取 ViewModel 实例_viewModel = Ioc.Default.GetService<MainViewModel>();// 设置数据上下文DataContext = _viewModel;}private void AddUser_Click(object sender, RoutedEventArgs e){_viewModel.AddUser();}private void RefreshUsers_Click(object sender, RoutedEventArgs e){_viewModel.RefreshUsers();}private void ShowIocInfo_Click(object sender, RoutedEventArgs e){// 演示 IOC 容器的使用var dataService = Ioc.Default.GetService<IDataService>();var notificationService = Ioc.Default.GetService<INotificationService>();var message = $"IOC 容器信息:\n\n" +$"DataService 实例: {dataService.GetType().Name}\n" +$"NotificationService 实例: {notificationService.GetType().Name}\n" +$"ViewModel 实例: {_viewModel.GetType().Name}\n\n" +$"所有服务都通过依赖注入获取!";notificationService.ShowMessage(message);}}
}
IOC 核心概念演示
1. 依赖注入容器配置
在 App.xaml.cs
中配置 IOC 容器:
private void ConfigureServices()
{var services = new ServiceCollection();// 注册服务(单例模式)services.AddSingleton<IDataService, DataService>();services.AddSingleton<INotificationService, NotificationService>();// 注册ViewModel(临时实例)services.AddTransient<MainViewModel>();// 配置到 CommunityToolkit.Mvvm 的 IOC 容器var serviceProvider = services.BuildServiceProvider();Ioc.Default.ConfigureServices(serviceProvider);
}
2. 构造函数注入
在 MainViewModel
中通过构造函数注入依赖:
public MainViewModel(IDataService dataService, INotificationService notificationService)
{_dataService = dataService;_notificationService = notificationService;LoadUsers();
}
3. 服务定位器模式
也可以通过 Ioc.Default
直接获取服务:
_dataService = Ioc.Default.GetService<IDataService>();
_notificationService = Ioc.Default.GetService<INotificationService>();
4. 在 View 中使用 IOC
在 MainWindow.xaml.cs
中从容器获取 ViewModel:
_viewModel = Ioc.Default.GetService<MainViewModel>();
DataContext = _viewModel;
项目特点
- 纯 IOC 功能展示:专注于依赖注入,不包含 Command、RelayCommand 等其他功能
- 接口导向设计:所有服务都通过接口定义,便于测试和扩展
- 生命周期管理:演示了 Singleton 和 Transient 生命周期
- 双重注入方式:展示构造函数注入和服务定位器两种方式
运行说明
- 确保安装了 .NET 8.0 SDK
- 在项目根目录运行
dotnet restore
- 运行
dotnet run
启动应用程序(或者直接点击绿色三角 快捷键Ctrl+F5) - 在界面中可以:
- 添加新用户
- 刷新用户列表
- 查看IOC容器信息
- 效果展示
学习要点
- IOC 容器配置:了解如何注册服务和配置依赖关系
- 依赖注入原理:理解如何通过构造函数注入获得松耦合
- 服务生命周期:掌握 Singleton 和 Transient 的区别
- 接口隔离:学习如何使用接口实现依赖倒置原则
- CommunityToolkit.Mvvm 集成:了解如何与 Microsoft.Extensions.DependencyInjection 集成