首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

在Avalonia/C#中使用依赖注入过程记录

  • 25-04-22 00:01
  • 2661
  • 10483
juejin.cn

前言

使用依赖注入可以让我们的程序变得更加好维护与测试。

今天分享的是在Avalonia/C#中使用依赖注入。

我准备了一个简单的不使用依赖注入与使用依赖注入的demo。

该demo已上传至GitHub,地址:github.com/Ming-jiayou…

因此本文中不会包含全部代码,有需要可以从GitHub获取全部代码。

实践

先运行一下AvaloniaWithoutDependencyInjection这个例子。

效果:

虽然我们实现了导航的功能,但是当重新点击的时候又会创建一个新的实例,并不会保留之前的状态,很多时候这不是我们想要的效果。

现在再来运行一下AvaloniaWithDependencyInjection这个例子。

效果:

由于我们以单例的形式将View与ViewModel注入了依赖注入容器中了,因此你可以看到现在再重新点击是会保留之前的状态了。

现在让我们一起看看如何将上面的那个例子改造成下面的那个例子吧!!

要实现依赖注入首先需要有一个依赖注入容器,我这里使用的是Microsoft.Extensions.DependencyInjection。

为了方便实现导航,我们创建一个INavigationService接口与NavigationService类。

INavigationService:

csharp
代码解读
复制代码
public interface INavigationService {    ViewModelBase CurrentViewModel { get; }    void NavigateTo<T>() where T : ViewModelBase; }

NavigationService:

csharp
代码解读
复制代码
public partial class NavigationService : ObservableObject, INavigationService {   [ObservableProperty]    private ViewModelBase _currentViewModel; ​    private readonly IServiceProvider _serviceProvider; ​    public NavigationService(IServiceProvider serviceProvider)   {        _serviceProvider = serviceProvider; ​        // 设置初始页面        NavigateTo();   } ​    public void NavigateTo<T>() where T : ViewModelBase   {        var viewModel = _serviceProvider.GetRequiredService();        CurrentViewModel = viewModel;   } }

为了方便添加服务,创建一个ServiceCollectionExtensions类。

swift
代码解读
复制代码
public static class ServiceCollectionExtensions {    public static IServiceCollection AddViews(this IServiceCollection services)   {        // Register all views as singletons        services.AddSingleton<MainWindow>();        services.AddSingleton<Page1View>();        services.AddSingleton<Page2View>();                return services;   }        public static IServiceCollection AddViewModels(this IServiceCollection services)   {        // Register all view models as singletons        services.AddSingleton<MainWindowViewModel>();        services.AddSingleton<Page1ViewModel>();        services.AddSingleton<Page2ViewModel>();                return services;   } ​    public static IServiceCollection AddServices(this IServiceCollection services)   {        services.AddSingleton<INavigationService, NavigationService>();        return services;   } }

在Program中注册服务:

image-20250421161136598

在App.axaml.cs中从容器中取出MainWindow与MainWindowViewModel:

image-20250421161251620

在ViewLocator中从容器中取出View的实例:

image-20250421161440244

MainWindowViewModel:

image-20250421161628346

经过以上步骤就成功在Avalonia中实现依赖注入了,现在来看看流程是怎么样的。

流程

程序启动在Program中注册了服务。

App.axaml.cs中取出了MainWindow与MainWindowViewModel。

在MainWindowViewModel中注入了INavigationService。

但是在这里你可能会有疑问:

image-20250421161943776

为什么这里可以直接使用serviceProvider呢?

看起来我们直接使用了serviceProvider,但实际上这里涉及到了依赖注入容器的生命周期和服务解析顺序。

当我们调用 services.BuildServiceProvider() 时,依赖注入容器会:

  • 创建一个服务提供者(ServiceProvider)实例
  • 这个 ServiceProvider 包含了所有注册的服务的信息和创建规则

当需要 NavigationService 时,依赖注入容器会:

  • 发现需要创建 NavigationService
  • 看到 NavigationService 的构造函数需要一个 IServiceProvider
  • 将自己(serviceProvider)作为参数传入
  • 创建 NavigationService 实例

在某处第一次请求INavigationService时发生的:

ini
代码解读
复制代码
var navigationService = serviceProvider.GetService();

此时:

  • serviceProvider 已经是完全初始化好的实例
  • 所有的 ViewModel 都已经注册完成
  • 当调用NavigateTo() 时,可以成功从容器中解析出 Page1ViewModel

然后初始导航到Page1ViewModel。

image-20250421162952745

从容器中取出Page1ViewModel并赋值给CurrentViewModel。

当CurrentViewModel改变的时候,会触发MainWindowViewModel订阅的这个属性变更事件:

image-20250421163436887

如果是CurrentViewModel属性发生变化,就将MainWindowViewModel中的CurrentPage属性赋值为CurrentViewModel。

CurrentPage类型为ViewModelBase,它的变化会触发ViewLocator中的Build方法:

image-20250421163718003

该方法会根据CurrentPage的类型从容器中取出对应的View,从而实现了导航的功能,并且能够保留之前的状态。

最后

以上就是在Avalonia/C#中使用依赖注入的过程,希望对你有所帮助。

注:本文转载自juejin.cn的mingupup的文章"https://juejin.cn/post/7495578098839339046"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

142
代码人生
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top