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容器

相关推荐
IT森林里的程序猿6 小时前
基于Hadoop的京东电商平台手机推荐系统的设计与实现
大数据·hadoop·智能手机
秃头菜狗7 小时前
十四、运行经典案例 wordcount
大数据·linux·hadoop
Java战神7 小时前
Hadoop
大数据·hadoop·分布式
Cathy Bryant8 小时前
球极平面投影
经验分享·笔记·数学建模
Larry_Yanan9 小时前
QML学习笔记(三十一)QML的Flow定位器
java·前端·javascript·笔记·qt·学习·ui
The_Killer.9 小时前
近世代数(抽象代数)详细笔记--环(也有域的相关内容)
笔记·学习·抽象代数·
Larry_Yanan9 小时前
QML学习笔记(三十)QML的布局器(Layouts)
c++·笔记·qt·学习·ui
不会kao代码的小王10 小时前
突破机房围墙:openEuler设备的公网管理实战指南
开发语言·数据库·笔记
c#上位机10 小时前
wpf之MVVM中只读属性更新界面
c#·wpf·mvvm
就是有点傻10 小时前
WPF自定义控件之环形进度条
wpf