Prism 源碼解讀4-ViewModel注入

介紹

介紹一個Prism的MVVM實現,主要介紹Prism如何在WPF上進行的一些封裝,以實現MVVM。MVVM究竟是什麼呢?看一下這一幅經典的圖數據庫

之前沒有ViewModel這個概念,就是將Model傳遞到View顯示,這樣軟件也能夠工做,但卻很混亂,一旦VIew要改動,一點點的改動都會形成不少代碼須要改動,不利於維護。再者VIew層充斥着各類解析Model的代碼,這些代碼徹底不屬於View啊。無緣無故的給View增長了不少職責。這是壞代碼的味道。因此就有了ViewModel。ViewModel負責幹什麼,必需要幹什麼,其實ViewModel的職責就是將本身的數據綁定到View顯示,同時數據變化須要通知View,View上客戶的操做及時響應,至於數據怎麼解析,從哪裏獲取,View的響應都應該方法後一層,能夠是Controller,能夠是Servicer,能夠是Presenter。也就是業務邏輯儘可能推到後一層。設計模式

試想一下,系統裏的Model有不少,有數據庫對應的數據庫模型,有業務於對應的領域模型,有用於數據交互的DTO也是模型,那麼對應的View有一個ViewModel也不以爲奇怪。框架

0 ViewModel定位

MVVM的第一步就是要解決ViewModel的依賴注入問題,框架如何不着痕跡的將View對應的VIewModel注入到依賴屬性DataContext。ide

還記得PrismApplicationBase類嗎,就是繼承Application,將整個Prism框架組件注入到Unity的那個類,設計

1585748254700

1585748299765

1585748279636

看到第一步是啥?ConfigureViewModelLocator,配置ViewModelLocator,急人之所急,Prism框架的第一步配置ViewModelLocator,3d

1585748453172

好吧,第一步就是設置ViewModelFactory,這個工廠就是經過View的類型和實例從Unity容器中獲取ViewModel實例。blog

1585748824956

1585748835165

噢!這個View參數還沒用上。繼承

再來看看這個包含ViewModelFactory的ViewModelLocationProvider。it

1585748957518

1585749152851

從這個名字咱們能夠大膽猜想,這個類應該是負責真正解析ViewModel的位置的,看到這個類的方法,有ViewModelFactory,有Register,有GetViewModelByXXX。io

1585749500406

這個類中一個委託字段_defaultViewTypeToViewModelTypeResolver,從這個字段咱們能夠看出是默認VIewModel解析方式,能夠看出就是把View完整類型名中的Views替換成ViewModels,而後返回Type,從這裏面咱們知道View的名字必定要含有Views,ViewModel必定要含有ViewModels。

1585751286821

好吧,知道了哪裏解析的再來看看哪裏調用的。

1585749866991

prism:ViewModelLocator.AutoWireViewModel="True",看到了,將ViewModelLocator的依賴屬性AutoWireViewModel至爲True,能夠進一步推測ViewModelLocator裏面確定調用了ViewModelLocationProvider的相關方法以得到ViewModel的類型或實例。

1585750033315

1585750054551

1585750076882

依賴屬性改變觸發了AutoWireViewModelChanged方法,而後調用ViewModelLocationProvider.AutoWireViewModelChanged

1585750149579

1585750194664

1585750209281

1585750223719

先去查看兩個字典,一個字典key是View是實例,另外一個字典key是View的Type,都沒有調用,而後調用ViewModelLocationProvider._defaultViewTypeToViewModelTypeResolver,也就是默認解析,在這邊解析得到VIewModel的類型,而後經過默認工廠得到ViewModel實例。並綁定到VIew的DataContext。

至此,知道了整個默認VIewModel解析的所有過程,梳理一下

  • 在程序開始向ViewModelLocationProvider中設置ViewModel類型工廠,也就是Unity。
  • ViewModelLocationProvider就是ViewModel獲取的地方有兩個字典都應該是存放viewmodel,有一個默認解析是經過View的type解析出ViewModel的type。
  • 在Xaml中經過ViewModelLocator的依賴屬性AutoWireViewModel調用ViewModelLocationProvider的AutoWireViewModelChanged來實現綁定。

1 自定義ViewModel定位

經過0的介紹,想一下怎麼自定義實現VIewModel定位,有幾種方法,

  1. 提早向ViewModelLocationProvider的字典中添加ViewModel的類型
  2. 改變_defaultViewTypeToViewModelTypeResolver解析方式
  3. 修改工廠。這個不能從根本上改變。

這個例子用的是第二種。

1585751155024

在程序的開始重寫ConfigureViewModelLocator方法,除了向ViewModelLocationProvider中添加ViewModelFactory外,還修改了_defaultViewTypeToViewModelTypeResolver解析方式。直接就經過View的type後面家長ViewModel,簡單粗暴。

1585751325000

2 自定義ViewModel解析

這種方法就是上面提到的1方法

  • 提早向ViewModelLocationProvider的字典中添加ViewModel的類型

1585751470206

這張方法顯然有很大的弊端,當程序中有不少View時怎麼能手動添加呢,只能適用與特殊的View和ViewModel的解析,如Shell的VIewModel的解析。

這種解析方法也不用在乎View和ViewModel的名字了。

總結

從ViewModel的解析中,咱們看到一種設計模式,View依賴ViewModelLocator,ViewModelLocator依賴ViewModelLocationProvider,ViewModelLocationProvider負責具體解析出對應的實例,至關於ViewModelRegistry,其中固然以有對工廠的依賴。

相關文章
相關標籤/搜索