文章目錄
- 專欄和Gitee倉庫
- 前言
- IOC容器
- Prism IOC使用
- 聲明兩個測試的服務類
- MainWindow IOC 注入[單例]
- MainWindow里面獲取
- UserController無法使用
- 官方解決方案
- 使用自定義IOC容器,完美解決
- 既然Prism不好用,直接上微軟的IOC
- 解決方案
- App.xaml.cs
- ViewModel里面直接調用
- 運行結果
- 總結
專欄和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)的使用
聲明兩個測試的服務類
namespace BlankApp1.Services
{public class TestA_Service{public string Name { get; set; }public TestA_Service() {Name = "小王";}}
}
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容器
/// <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里面獲取
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
/// <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里面直接調用
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 程序進行無限拆分。