在Avalonia/C#中使用依赖注入过程记录
前言
使用依赖注入可以让我们的程序变得更加好维护与测试。
今天分享的是在Avalonia/C#中使用依赖注入。
我准备了一个简单的不使用依赖注入与使用依赖注入的demo。
该demo已上传至GitHub,地址: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<T>() 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<Page1ViewModel>();
}
public void NavigateTo<T>() where T : ViewModelBase
{
var viewModel = _serviceProvider.GetRequiredService<T>();
CurrentViewModel = viewModel;
}
}
为了方便添加服务,创建一个ServiceCollectionExtensions类。
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中注册服务:
在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<INavigationService>();
此时:
serviceProvider
已经是完全初始化好的实例所有的
ViewModel
都已经注册完成当调用
NavigateTo<Page1ViewModel>
() 时,可以成功从容器中解析出Page1ViewModel
然后初始导航到Page1ViewModel
。
从容器中取出Page1ViewModel并赋值给CurrentViewModel。
当CurrentViewModel改变的时候,会触发MainWindowViewModel订阅的这个属性变更事件:
如果是CurrentViewModel属性发生变化,就将MainWindowViewModel中的CurrentPage属性赋值为CurrentViewModel。
CurrentPage类型为ViewModelBase,它的变化会触发ViewLocator中的Build方法:
该方法会根据CurrentPage的类型从容器中取出对应的View,从而实现了导航的功能,并且能够保留之前的状态。
最后
以上就是在Avalonia/C#中使用依赖注入的过程,希望对你有所帮助。
在Avalonia/C#中使用依赖注入过程记录的更多相关文章
- 在WPF中使用依赖注入的方式创建视图
在WPF中使用依赖注入的方式创建视图 0x00 问题的产生 互联网时代桌面开发真是越来越少了,很多应用都转到了浏览器端和移动智能终端,相应的软件开发上的新技术应用到桌面开发的文章也很少.我之前主要做W ...
- ASP.NET Core中的依赖注入(1):控制反转(IoC)
ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了"标准化&qu ...
- ASP.NET Core中的依赖注入(2):依赖注入(DI)
IoC主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...
- ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理
ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...
- NET Core 中的依赖注入
NET Core 中的依赖注入 [共7篇] 一.控制反转(IoC) ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制, ...
- .NET CORE——Console中使用依赖注入
我们都知道,在 ASP.NET CORE 中通过依赖注入的方式来使用服务十分的简单,而在 Console 中,其实也只是稍微绕了个小弯子而已.不管是内置 DI 组件或者第三方的 DI 组件(如Auto ...
- Asp.net core中的依赖注入
使用服务 在Asp.net core的Controller中,可以通过如下两种方式获取系统注入的服务: 构造函数 可以直接在构造函数中传入所依赖的服务,这是非常常见的DI注入方式. public Va ...
- 深入理解net core中的依赖注入、Singleton、Scoped、Transient(四)
相关文章: 深入理解net core中的依赖注入.Singleton.Scoped.Transient(一) 深入理解net core中的依赖注入.Singleton.Scoped.Transient ...
- 深入理解net core中的依赖注入、Singleton、Scoped、Transient(三)
相关文章: 深入理解net core中的依赖注入.Singleton.Scoped.Transient(一) 深入理解net core中的依赖注入.Singleton.Scoped.Transient ...
- 深入理解net core中的依赖注入、Singleton、Scoped、Transient(二)
相关文章: 深入理解net core中的依赖注入.Singleton.Scoped.Transient(一) 深入理解net core中的依赖注入.Singleton.Scoped.Transient ...
随机推荐
- gitblit 安装
github 私有代码库收费属于正常商业操作,毕竟现在鼓励开源,但是受到美国出口管制,这就有些不妙了. 所以有必要自己搭建一个私有的托管服务,经过比较并且,选择了gitblit(因为最近偶尔搞搞jav ...
- JMeter下载与环境配置
前置 使用JMeter前需要先配置好Java的环境变量,不会的朋友可以阅读:https://www.cnblogs.com/test-gang/p/18144441 JMeter下载 JMeter官网 ...
- 耳分解、双极定向和 P9394 Solution
耳分解 设无向图 \(G'(V',E')\subset G(V,E)\),简单路径或简单环 \(P:x_1\to \dots \to x_k\) 被称为 \(G\) 关于 \(G'\) 的耳,当且仅当 ...
- HBase多租户分组
一.分组简介 RegionServer Group 通过对 RegionServer 进行分组,不同的 RegionServer 分到不同的组.每个组可以按需挂载不同的表,并且当组内的表发生异常后,R ...
- Luogu P3177 树上染色 [ 蓝 ] [ 树形 dp ] [ 贡献思维 ]
一道很好的树形 dp !!!!! 树上染色. 错误思路 定义 \(dp[u][i]\) 表示以 \(u\) 为根的子树中,把 \(i\) 个点染成黑色的最大收益. 但这样写,就在转移的时候必须枚举每一 ...
- 普通人也能轻松掌握的20个DeepSeek高频提示词(2025版)
一.基础原则 1️⃣ 说人话最重要 "不用专业术语,就像和朋友聊天一样描述需求". ️ 错误示范:"请用SWOT分析法输出新能源汽车行业报告". 正确示范:&q ...
- LeetCode 题解大全
项目说明 LeetCode 系列题解致力于帮助程序员更好地理解和掌握算法思维,内容包含详细的解题思路分析.图文并茂的示例讲解和完整的代码实现. LeetCode 最全题解:持续更新中,欢迎 Star ...
- C# Windows Service 安装与卸载
安装与卸载的使用工具 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe (一般安装了.NetFramework 后就会有该 ...
- ssh远程连接linux服务器
Linux,ssh远程连接 一. linux端配置 1.安装ssh服务 sudo apt-get update sudo apt-get install openssh-client sudo apt ...
- 另类方式实现.Net下的多语言
前言 关于.Net下的多语言方案已经有很多成熟的方案,例如:# Avalonia 国际化之路:Resx 资源文件的深度应用与探索,或者# Avalonia使用XML文件实现国际化,基本都围绕官方的Sa ...