WPF仿网易云搭建笔记(5):信息流控制之IOC容器

文章目录

专栏和Gitee仓库

WPF仿网易云 Gitee仓库
WPF仿网易云 CSDN博客专栏

前言

上一篇文章中,我们简单讲解了一下父子通讯的逻辑。父子通讯是强绑定逻辑。这里我们将讲解消息订阅通讯的方式。消息订阅一般用于[页]和[页]之间通讯。

IOC容器

IOC容器有许多容器,目前.NET 有两个最优的依赖注入框架

  • Microsoft.Extensions.DependencyInjection:微软官方依赖注入框架,听说在.net core 8.0得到了最强的性能提升
  • Autofac:听说也是最强的依赖注入框架,性能强,开销低,功能完善。

Dependency injection in ASP.NET Core
Autofac 官网
深入浅出依赖注入容器------Autofac
.NET Core 依赖注入 Microsoft.Extensions.DependencyInjection

当然,Prism也有自己的IOC容器。

WPF Prims框架详解

我们这里使用Prism的IOC容器。因为Prism提供了全套的解决方案

Prism IOC使用

我之前使用过微软的IOC,这里我就不展开说明了。IOC容器的使用都是大差不多的。

Prism.Unity 依赖注入(IOC)的使用

声明两个测试的服务类

csharp 复制代码
namespace BlankApp1.Services
{
    public class TestA_Service
    {
        public string Name { get; set; }

        public TestA_Service() {
            Name = "小王";
        }
    }
}
csharp 复制代码
namespace BlankApp1.Services
{
    public class TestB_Service
    {
        public TestA_Service TestA_Serivce { get; set; }

        public string Name { get; set; }


        public TestB_Service(TestA_Service testA_Serivce)
        {
            TestA_Serivce = testA_Serivce;
            Name = "小红";
        }
    }
}

MainWindow IOC 注入[单例]

我们目前所有注入的IOC容器实例都是单例注入,生命周期暂时不考虑。

在App.xaml里面注入IOC容器

csharp 复制代码
        /// <summary>
        /// 这里是IOC容器的注入端口
        /// </summary>
        /// <param name="containerRegistry"></param>
        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            //这里对TestA_Service进行修改,查看IOC容器是否为单例。
            containerRegistry.RegisterSingleton<TestA_Service>(sp =>
            {
                return new TestA_Service()
                {
                    Name = "小丽",
                };
            });
            containerRegistry.RegisterSingleton<TestB_Service>();
            //注入MainWindow,这里注入先后没有影响
            containerRegistry.RegisterSingleton<MainWindow>();
        }

MainWindow里面获取

csharp 复制代码
public MainWindow(TestB_Service testB_Service)
{
    InitializeComponent();
    ViewModel = (MainWindowViewModel)DataContext;
    ViewModel.MainWindow = this;
    ViewModel.TestB_Service = testB_Service;
}

结果:获取成功!

UserController无法使用

但是如果我们使用TitleView会怎么样?


原因是为什么?因为是因为我们使用的是父子组件构造,但是这样WPF默认使用的是New 一个新对象,是无参构造。所以会报这个错误。

官方解决方案

Composing the User Interface Using the Prism Library for WPF

官方的解决比较简单粗暴,官方认为所有的UserController都是Prism构造的,这里面使用的是Prism的Region方案。所有的信息流都是通过Messager去设置的,如果是这样设置的话,我们所有的父子通讯都失败了。而且由于Messager的单一化,导致我们无法复用组件,因为如果存在多个组件ViewA,你不能确认ViewA到底是哪个ViewA,这个和我们的单例注入相违背。

使用自定义IOC容器,完美解决

Prism最大的问题,就是他是侵入式框架,你必须按照Prism的解决方案才能解决问题。而且给的方案都比较死。

既然Prism不好用,直接上微软的IOC

为什么要用微软的IOC容器,一个是微软的好用,另一个是ASP.NET Core也都是微软的IOC。能用一个解决就不学新的。

.NET Core 依赖注入 Microsoft.Extensions.DependencyInjection

解决方案

App.xaml.cs

csharp 复制代码
/// <summary>
/// 全局静态IOC构造器
/// </summary>
public readonly static ServiceProvider ServiceProvider;

/// <summary>
/// 静态构造,这里以单例举例
/// </summary>
static App() {
    IServiceCollection services = new ServiceCollection();
    services.AddSingleton<TestB_Service>();
    services.AddSingleton<TestA_Service>(sp =>
    {
        return new TestA_Service()
        {
        	//测试是否被修改。默认小王,修改为小兰
            Name = "小兰"
        };
    });
    ServiceProvider = services.BuildServiceProvider();
    var res = ServiceProvider.GetService<MainWindowViewModel>();
}

ViewModel里面直接调用

csharp 复制代码
public MainWindowViewModel()
{
    //直接从构造器里面拿到单例
    TestB_Service = App.ServiceProvider.GetService<TestB_Service>();
}

运行结果

其实通过Service可以进行间接通讯。这里我就不展开说明了。

总结

因为父子组件开发的特点,所有的UserController都可能存在多个,所以UserController是不能进行IOC的。因为IOC会有两个源,一个是Xaml实例化,另一个是IOC容器。还有一个问题是Xaml语法是不能进行IOC的,而且由于生命周期的原因,IOC实例化之前会报错。所以直接放弃UserController的IOC注入。

但是Services服务类可以进行IOC注入,比如数据库操作,网络通讯,业务逻辑(比如用户登录)。

我们目前已经完美解决了WPF 的信息流控制。通过WPF的组件化开发,消息订阅,IOC容器。大大降低了WPF项目的耦合,让我们可以将所有复杂的WPF 程序进行无限拆分。
DataContext强绑定,依赖属性暴露 父子组件通讯,Message消息订阅 IOC构造 IOC取出 View ViewModel ViewA Services IOC容器

相关推荐
Warren981 小时前
Appium学习笔记
android·windows·spring boot·笔记·后端·学习·appium
IT研究室1 小时前
大数据毕业设计选题推荐-基于大数据的餐饮服务许可证数据可视化分析系统-Spark-Hadoop-Bigdata
大数据·hadoop·spark·毕业设计·源码·数据可视化·bigdata
彤银浦1 小时前
PHP学习笔记1
笔记·学习·php
ReedFoley13 小时前
【笔记】动手学Ollama 第七章 应用案例1 搭建本地AI Copilot编程助手
人工智能·笔记·copilot
长安即是故里14 小时前
Maxwell学习笔记
笔记·学习
咸甜适中15 小时前
rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(十四)垂直滚动条
笔记·学习·rust·egui
努力敲代码的小盆友16 小时前
[自用笔记]上传本地项目至github
笔记·github
myself16 小时前
Hadoop中的MapReduce学习 - Mapper和shuffle阶段
hadoop
IT研究室17 小时前
大数据毕业设计选题推荐-基于大数据的北京市医保药品数据分析系统-Spark-Hadoop-Bigdata
大数据·hadoop·spark·毕业设计·源码·数据可视化
It_张17 小时前
Building Systems with the ChatGPT API 使用 ChatGPT API 搭建系统(第五章学习笔记及总结)
笔记·学习·chatgpt