在Avalonia/C#中使用依赖注入过程记录
笔记哥 /
04-21 /
9点赞 /
0评论 /
120阅读
## 前言
使用依赖注入可以让我们的程序变得更加好维护与测试。
今天分享的是在Avalonia/C#中使用依赖注入。
Demo地址:https://github.com/Ming-jiayou/Avalonia\_With\_Dependency\_Injection\_Example
因此本文中不会包含全部代码,有需要可以从GitHub获取全部代码。
## 实践
先运行一下AvaloniaWithoutDependencyInjection这个例子。
效果:

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

由于我们以单例的形式将View与ViewModel注入了依赖注入容器中了,因此你可以看到现在再重新点击是会保留之前的状态了。
现在让我们一起看看如何将上面的那个例子改造成下面的那个例子吧!!
要实现依赖注入首先需要有一个依赖注入容器,我这里使用的是Microsoft.Extensions.DependencyInjection。
为了方便实现导航,我们创建一个INavigationService接口与NavigationService类。
INavigationService:
```csharp
public interface INavigationService
{
ViewModelBase CurrentViewModel { get; }
void NavigateTo() 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() where T : ViewModelBase
{
var viewModel = \_serviceProvider.GetRequiredService();
CurrentViewModel = viewModel;
}
}
```
为了方便添加服务,创建一个ServiceCollectionExtensions类。
```csharp
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddViews(this IServiceCollection services)
{
// Register all views as singletons
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
return services;
}
public static IServiceCollection AddViewModels(this IServiceCollection services)
{
// Register all view models as singletons
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
return services;
}
public static IServiceCollection AddServices(this IServiceCollection services)
{
services.AddSingleton();
return services;
}
}
```
在Program中注册服务:

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

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

MainWindowViewModel:

经过以上步骤就成功在Avalonia中实现依赖注入了,现在来看看流程是怎么样的。
## 流程
程序启动在Program中注册了服务。
App.axaml.cs中取出了MainWindow与MainWindowViewModel。
在MainWindowViewModel中注入了INavigationService。
但是在这里你可能会有疑问:

为什么这里可以直接使用`serviceProvider`呢?
看起来我们直接使用了` serviceProvider`,但实际上这里涉及到了依赖注入容器的生命周期和服务解析顺序。
当我们调用 `services.BuildServiceProvider()` 时,依赖注入容器会:
- 创建一个服务提供者(`ServiceProvider`)实例
- 这个 `ServiceProvider `包含了所有注册的服务的信息和创建规则
当需要 `NavigationService `时,依赖注入容器会:
- 发现需要创建 `NavigationService`
- 看到 `NavigationService `的构造函数需要一个 `IServiceProvider`
- 将自己(`serviceProvider`)作为参数传入
- 创建 `NavigationService` 实例
在某处第一次请求`INavigationService`时发生的:
```csharp
var navigationService = serviceProvider.GetService();
```
此时:
- `serviceProvider `已经是完全初始化好的实例
- 所有的 `ViewModel `都已经注册完成
- 当调用` NavigateTo`() 时,可以成功从容器中解析出 `Page1ViewModel`
然后初始导航到`Page1ViewModel`。

从容器中取出Page1ViewModel并赋值给CurrentViewModel。
当CurrentViewModel改变的时候,会触发MainWindowViewModel订阅的这个属性变更事件:

如果是CurrentViewModel属性发生变化,就将MainWindowViewModel中的CurrentPage属性赋值为CurrentViewModel。
CurrentPage类型为ViewModelBase,它的变化会触发ViewLocator中的Build方法:

该方法会根据CurrentPage的类型从容器中取出对应的View,从而实现了导航的功能,并且能够保留之前的状态。
## 最后
以上就是在Avalonia/C#中使用依赖注入的过程,希望对你有所帮助。
本文来自投稿,不代表本站立场,如若转载,请注明出处:http//www.knowhub.vip/share/2/2452
- 热门的技术博文分享
- 1 . ESP实现Web服务器
- 2 . 从零到一:打造高效的金仓社区 API 集成到 MCP 服务方案
- 3 . 使用C#构建一个同时问多个LLM并总结的小工具
- 4 . .NET 原生驾驭 AI 新基建实战系列Milvus ── 大规模 AI 应用的向量数据库首选
- 5 . 在Avalonia/C#中使用依赖注入过程记录
- 6 . [设计模式/Java] 设计模式之工厂方法模式
- 7 . 5. RabbitMQ 消息队列中 Exchanges(交换机) 的详细说明
- 8 . SQL 中的各种连接 JOIN 的区别总结!
- 9 . JavaScript 中防抖和节流的多种实现方式及应用场景
- 10 . SaltStack 远程命令执行中文乱码问题
- 11 . 推荐10个 DeepSeek 神级提示词,建议搜藏起来使用
- 12 . C#基础:枚举、数组、类型、函数等解析
- 13 . VMware平台的Ubuntu部署完全分布式Hadoop环境
- 14 . C# 多项目打包时如何将项目引用转为包依赖
- 15 . Chrome 135 版本开发者工具(DevTools)更新内容
- 16 . 从零创建npm依赖,只需执行一条命令
- 17 . 关于 Newtonsoft.Json 和 System.Text.Json 混用导致的的序列化不识别的问题
- 18 . 大模型微调实战之训练数据集准备的艺术与科学
- 19 . Windows快速安装MongoDB之Mongo实战
- 20 . 探索 C# 14 新功能:实用特性为编程带来便利