在AvaloniaC#中使用依赖注入过程记录
- 作者: 五速梦信息网
- 时间: 2026年03月21日 04:48
前言
使用依赖注入可以让我们的程序变得更加好维护与测试。 今天分享的是在Avalonia/C#中使用依赖注入。 Demo地址:https://github.com/Ming-jiayou/Avalonia_With_Dependency_Injection_Example 因此本文中不会包含全部代码,有需要可以从GitHub获取全部代码。
实践
先运行一下AvaloniaWithoutDependencyInjection这个例子。
效果:
虽然我们实现了导航的功能,但是当重新点击的时候又会创建一个新的实例,并不会保留之前的状态,很多时候这不是我们想要的效果。
现在再来运行一下AvaloniaWithDependencyInjection这个例子。
效果:
由于我们以单例的形式将View与ViewModel注入了依赖注入容器中了,因此你可以看到现在再重新点击是会保留之前的状态了。
现在让我们一起看看如何将上面的那个例子改造成下面的那个例子吧!!
要实现依赖注入首先需要有一个依赖注入容器,我这里使用的是Microsoft.Extensions.DependencyInjection。
为了方便实现导航,我们创建一个INavigationService接口与NavigationService类。
INavigationService:
public interface INavigationService
{
ViewModelBase CurrentViewModel { get; }
void NavigateTo() where T : ViewModelBase;
}
NavigationService:
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类。
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时发生的:
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#中使用依赖注入的过程,希望对你有所帮助。
相关文章
-
在 .NET 中使用 Sqids 快速的为数字 ID 披上神秘短串,轻松隐藏敏感数字!
在 .NET 中使用 Sqids 快速的为数字 ID 披上神秘短串,轻松隐藏敏感数字!
- 互联网
- 2026年03月21日
-
再看 风弄,非天,淮上,priest在耽美圈里排名
再看 风弄,非天,淮上,priest在耽美圈里排名
- 互联网
- 2026年03月21日
-
云端同步(云端同步文件巧管理)
云端同步(云端同步文件巧管理)
- 互联网
- 2026年03月21日
-
在IM即时通讯系统中接入DeepSeek等AI大模型
在IM即时通讯系统中接入DeepSeek等AI大模型
- 互联网
- 2026年03月21日
-
在java中为什么重写equals一定也要重写hashCode方法?
在java中为什么重写equals一定也要重写hashCode方法?
- 互联网
- 2026年03月21日
-
在windows11 安装CUDA Toolkit,Python,Anaconda,PyTorch并使用DeepSeek 多模态模型 Janus
在windows11 安装CUDA Toolkit,Python,Anaconda,PyTorch并使用DeepSeek 多模态模型 Janus
- 互联网
- 2026年03月21日


