Skip to content

一个基于 CommunityToolkit.Mvvm 的源生成器项目,自动生成 ViewModel 绑定代码,简化 MVVM 模式的实现。

License

Notifications You must be signed in to change notification settings

hippieZhou/SourceGeneratorExample

Repository files navigation

MVVM Toolkit 源生成器示例项目

一个基于 CommunityToolkit.Mvvm 的源生成器项目,自动生成 ViewModel 绑定代码,简化 MVVM 模式的实现。

🚀 项目特性

  • 自动 ViewModel 绑定: 通过 [AutoViewModel] 特性自动生成绑定代码
  • 依赖注入支持: 完整集成 CommunityToolkit.Mvvm 的 IoC 容器
  • 智能类型处理: 自动识别 Window 类型并智能处理 DataContext 设置
  • 类型安全: 编译时类型检查,避免运行时错误
  • 灵活配置: 支持多种配置选项满足不同需求

📖 快速开始

1. 基本用法

在你的 View 类上添加 [AutoViewModel] 特性:

using MvvmTooklit.Attributes;
using SourceGeneratorExample.ViewModels;

[AutoViewModel(typeof(MainPageViewModel))]
public sealed partial class MainPage : Page
{
    public MainPage()
    {
        InitializeComponent();
        InitializeViewModel(); // 自动生成的方法
    }
}

2. 配置依赖注入

App.xaml.cs 中配置 IoC 容器:

private void ConfigureServices()
{
    var services = new ServiceCollection();
    
    // 注册服务
    services.AddSingleton<IUserService, UserService>();
    
    // 注册 ViewModels
    services.AddTransient<MainPageViewModel>();
    services.AddTransient<MainWindowViewModel>();

    // 配置 CommunityToolkit.Mvvm 的 IoC 容器
    var serviceProvider = services.BuildServiceProvider();
    Ioc.Default.ConfigureServices(serviceProvider);
}

3. 创建 ViewModel

public partial class MainPageViewModel : ObservableObject
{
    private readonly IUserService _userService;

    public MainPageViewModel(IUserService userService)
    {
        _userService = userService;
        // 初始化逻辑...
    }
}

⚙️ AutoViewModel 配置选项

AutoViewModelAttribute 支持以下配置选项:

[AutoViewModel(typeof(MyViewModel), 
    PropertyName = "MyViewModel",           // ViewModel 属性名(默认:"ViewModel")
    SetDataContext = false,                 // 是否自动设置 DataContext(默认:true)
    ResolveFromContainer = false)]          // 是否从容器解析(默认:true)
public partial class MyView : Page
{
    // ...
}

配置说明

属性 类型 默认值 说明
PropertyName string "ViewModel" 生成的 ViewModel 属性名称
SetDataContext bool true 是否自动设置 DataContext(Window 类型会自动忽略)
ResolveFromContainer bool true 是否从 DI 容器解析 ViewModel

🔧 ResolveFromContainer 详解

从容器解析 (ResolveFromContainer = true)

// 生成的代码
ViewModel = Ioc.Default.GetService<MyViewModel>();

优势:

  • 支持构造函数依赖注入
  • 遵循 MVVM 最佳实践
  • 适合复杂应用架构

直接创建实例 (ResolveFromContainer = false)

// 生成的代码
ViewModel = Activator.CreateInstance<MyViewModel>();

优势:

  • 简单直接,无需配置 DI
  • 适合简单的 ViewModel
  • 减少外部依赖

🏗️ 项目结构

SourceGeneratorExample/
├── MvvmTooklit/                    # 核心库
│   ├── Attributes/
│   │   └── AutoViewModelAttribute.cs
│   └── Services/
│       └── ServiceLocator.cs
├── MvvmTooklit.Gen/               # 源生成器
│   └── Generators/
│       └── ViewModelAutoBindGenerator.cs
└── SourceGeneratorExample/        # 示例应用
    ├── ViewModels/
    │   ├── MainPageViewModel.cs
    │   └── MainWindowViewModel.cs
    └── Views/
        ├── MainPage.xaml
        ├── MainPage.xaml.cs
        ├── MainWindow.xaml
        └── MainWindow.xaml.cs

💡 使用示例

Window 类型

[AutoViewModel(typeof(MainWindowViewModel))]
public sealed partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        InitializeViewModel();
        // Window 类型不会自动设置 DataContext
        // 需要手动设置子元素的 DataContext
    }
}

Page/UserControl 类型

[AutoViewModel(typeof(MainPageViewModel))]
public sealed partial class MainPage : Page
{
    public MainPage()
    {
        InitializeComponent();
        InitializeViewModel();
        // 自动设置 this.DataContext = ViewModel
    }
}

自定义配置

[AutoViewModel(typeof(CustomViewModel), 
    PropertyName = "MyViewModel",
    SetDataContext = false,
    ResolveFromContainer = false)]
public sealed partial class CustomView : UserControl
{
    public CustomView()
    {
        InitializeComponent();
        InitializeViewModel();
        // 手动设置 DataContext
        this.DataContext = MyViewModel;
    }
}

🔨 构建和运行

  1. 克隆项目

    git clone <repository-url>
    cd SourceGeneratorExample
  2. 打开解决方案

    • 使用 Visual Studio 2022 打开 SourceGeneratorExample.sln
  3. 构建项目

    • 构建解决方案 (Ctrl+Shift+B)
    • 源生成器会自动生成绑定代码
  4. 运行示例

    • 设置 SourceGeneratorExample 为启动项目
    • 按 F5 运行

🐛 调试源生成器

参考:dotnet-how-to-debug-source-generator-vs2022

前提条件

确保已安装 .NET Compiler Platform SDK

调试配置步骤

项目已预配置了调试所需的设置,可以直接进行调试:

  1. 配置调试启动配置文件

    • 右键点击 MvvmTooklit.Gen 项目
    • 选择 Properties(属性)
    • 点击 Debug(调试)
    • 点击 Open debug launch profiles UI(打开调试启动配置文件 UI)
  2. 添加 Roslyn 组件调试配置

    • 如果已有配置文件,点击 Delete(删除) 删除现有配置
    • 点击 Add(添加)
    • 选择 Roslyn component
    • Target project(目标项目) 中选择 SourceGeneratorExample
    • 关闭 UI
  3. 重启 Visual Studio

    • 关闭并重新启动 Visual Studio 2022
    • 重新打开解决方案
  4. 开始调试

    • 在调试配置文件下拉菜单中选择 MvvmTooklit.Gen 项目
    • 在源生成器代码中设置断点(如 ViewModelAutoBindGenerator.cs
    • 点击 Play(播放) 按钮开始调试

调试技巧

  1. 设置断点位置

    // 在 ViewModelAutoBindGenerator.cs 中的关键方法设置断点
    private static void Execute(Compilation compilation, ImmutableArray<ViewInfo?> views, SourceProductionContext context)
    {
        // 在这里设置断点 👈
        foreach (var viewInfo in views)
        {
            // ...
        }
    }
  2. 查看生成的代码

    • 生成的文件位于:MvvmTooklit.Gen/Generated/ 目录
    • 也可以在 Solution Explorer 中展开项目节点查看生成的文件
  3. 调试输出

    // 在源生成器中添加调试输出
    System.Diagnostics.Debug.WriteLine($"Processing view: {viewInfo.ViewSymbol.Name}");

重要注意事项

⚠️ 每次修改源生成器代码后,都需要重启 Visual Studio,否则重新构建目标项目时不会使用新版本。这与 Visual Studio 的缓存机制有关。

调试流程

  1. 在源生成器中设置断点
  2. 启动调试 (F5)
  3. Visual Studio 会:
    • 启动新的 VS 实例
    • 加载目标项目 (SourceGeneratorExample)
    • 触发源生成器执行
    • 在断点处暂停

项目配置说明

项目已预配置了调试所需的设置:

MvvmTooklit.Gen.csproj:

<PropertyGroup>
  <TargetFramework>netstandard2.0</TargetFramework>
  <IsRoslynComponent>true</IsRoslynComponent>
  <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
  <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

SourceGeneratorExample.csproj:

<ProjectReference 
  Include="..\MvvmTooklit.Gen\MvvmTooklit.Gen.csproj" 
  OutputItemType="Analyzer" 
  ReferenceOutputAssembly="false"/>

🛠️ 技术栈

  • .NET 8.0
  • WinUI 3
  • CommunityToolkit.Mvvm
  • Microsoft.CodeAnalysis
  • 源生成器技术

📋 要求

  • Visual Studio 2022 17.0+
  • .NET 8.0 SDK
  • Windows 10 版本 1809 (Build 17763) 或更高版本

🤝 贡献

欢迎提交 Issue 和 Pull Request 来改进这个项目!

📄 许可证

本项目基于 MIT 许可证开源。

相关参考

About

一个基于 CommunityToolkit.Mvvm 的源生成器项目,自动生成 ViewModel 绑定代码,简化 MVVM 模式的实现。

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages