翻譯|行業(yè)資訊|編輯:龔雪|2022-05-30 10:21:29.753|閱讀 282 次
概述:本文主要介紹WPF MVVM應(yīng)用程序中的依賴注入并演示如何設(shè)置,歡迎下載相關(guān)工具體驗(yàn)~
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
當(dāng)解決方案的規(guī)模和范圍擴(kuò)大時,保持整體應(yīng)用程序的靈活性變得更加困難。 對象之間的依賴關(guān)系不斷增長,更改一個類可能需要更新其他類,依賴注入 (DI) 可以幫助解決這一挑戰(zhàn)。
如您所知,依賴注入是“控制反轉(zhuǎn)”(IoC)編程原理的一種形式。 這意味著類不會創(chuàng)建它們所依賴的對象,DI 框架具有負(fù)責(zé)揭示和解決依賴關(guān)系的容器。
假設(shè)您有一個使用數(shù)據(jù)服務(wù)獲取數(shù)據(jù)的視圖模型:
public class UserViewModel
{
MyDataService dataService;
public UserViewModel() {
this.dataService = new MyDataService();
}
}
視圖模型依賴于一個服務(wù)——這意味著 MyDataService 是 UserViewModel 的依賴,直接在視圖模型類中創(chuàng)建服務(wù)非常容易,但是這種方法有幾個缺點(diǎn):
如果將 MyDataService 傳遞給 UserViewModel 的構(gòu)造函數(shù),則可以避免這些問題:
public class UserViewModel
{
MyDataService dataService;
public UserViewModel(MyDataService dataService) {
this.dataService = dataService;
}
}
不幸的是,這種技術(shù)也有缺陷:
依賴注入的主要思想是集中解決所有依賴,這意味著您的程序中有一個單獨(dú)的塊來初始化新的類實(shí)例并將參數(shù)傳遞給它們。 盡管您可以為此實(shí)現(xiàn)自己的邏輯,但使用 DI 框架來幫助避免/消除示例代碼會更方便。
依賴注入模式具有以下優(yōu)點(diǎn):
.NET 社區(qū)有許多很棒的框架來幫助您在應(yīng)用程序中實(shí)現(xiàn)依賴注入模式,所有這些框架都有兩個主要特點(diǎn):
容器是 DI 框架中的中心對象,可以自動檢測和解決類依賴關(guān)系。 某些框架可以將參數(shù)注入類屬性,但最常見的方法是將參數(shù)注入構(gòu)造函數(shù)。
讓我們修改 MainViewModel 構(gòu)造函數(shù),使其接受接口替代類:
public class MainViewModel
{
IDataService dataService;
public MainViewModel(IDataService dataService) {
this.dataService = dataService;
}
}
這將允許您在將來使用不同的 IDataService 實(shí)現(xiàn)。
進(jìn)行此更改后,我們需要創(chuàng)建一個 DI 容器來注冊 MyDataService 并實(shí)例化 MainViewModel:
protected override void OnStartup(StartupEventArgs e) {
base.OnStartup(e);
var builder = new ContainerBuilder();
//allow the Autofac container resolve unknown types
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
//register the MyDataService class as the IDataService interface in the DI container
builder.RegisterType<MyDataService>().As<IDataService>().SingleInstance();
IContainer container = builder.Build();
//get a MainViewModel instance
MainViewModel mainViewModel = container.Resolve<MainViewModel>();
}
在此示例中,我們使用了 Autofac 框架,但您可以使用任何其他 DI 框架,例如 Unity 或 Ninject。 DI 容器創(chuàng)建 MainViewModel 并自動將 MyDataService 注入 MainViewModel 構(gòu)造函數(shù),這允許您在每次創(chuàng)建具有 IDataService 參數(shù)類型的類時避免 MyDataService 初始化。
然后我們需要將 MainViewModel 連接到它的視圖:MainView,最明顯的策略是在視圖構(gòu)造函數(shù)中設(shè)置 DataContext:
public MainView() {
InitializeComponent();
this.DataContext = container.Resolve<MainViewModel>();
}
但是,要訪問 DI 容器,您必須將其設(shè)為靜態(tài)或?qū)⑵鋫鬟f給每個視圖構(gòu)造函數(shù)。 一個更好的解決方案是創(chuàng)建一個標(biāo)記擴(kuò)展,它根據(jù)其類型返回一個視圖模型實(shí)例:
public class DISource : MarkupExtension
{
public static Func<Type, object> Resolver { get; set; }
public Type Type { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider) => Resolver?.Invoke(Type);
}
<UserControl DataContext="{local:DISource Type=local:MainViewModel}">
最初,標(biāo)記擴(kuò)展未綁定到任何 DI 容器。 要允許擴(kuò)展使用您的容器,請按以下方式指定視圖模型解析器:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e) {
base.OnStartup(e);
//...
IContainer container = builder.Build();
DISource.Resolver = (type) => {
return container.Resolve(type);
};
}
}
這種技術(shù)允許 DISource 與任何可能的容器一起工作。
在上面的示例中,我們使用了不與可視控件通信的抽象數(shù)據(jù)服務(wù)。 如您所知,許多DevExpress WPF服務(wù)使用視圖控件,因此服務(wù)必須知道使用哪個控件。 例如,如果您希望將 NavigationFrameService 注入到視圖模型中,還需要將此服務(wù)附加到相應(yīng)的 NavigationFrame 控件。
在視圖模型中創(chuàng)建一個包含服務(wù)的公共屬性,并將服務(wù)綁定到 NavigationFrame:
public class MainViewModel {
public INavigationService NavigationService { get; }
public MainViewModel(INavigationService navigationService) =>
NavigationService = navigationService;
}
<dxwui:NavigationFrame>
<dxmvvm:Interaction.Behaviors>
<common:AttachServiceBehavior Service="{Binding NavigationService}"/>
</dxmvvm:Interaction.Behaviors>
</dxwui:NavigationFrame>
AttachServiceBehavior 是一個簡單的附加操作,它在服務(wù)屬性更改時調(diào)用 NavigationFrameService.Attach。 雖然 AttachServiceBehavior 不包含在我們的庫中,但您可以在此處獲取其代碼:。即使 MainViewModel 使用 NavigationFrameService,它也不必實(shí)現(xiàn) ISupportServices 接口。 此外,導(dǎo)航中涉及的所有子視圖都可以在不附加到 NavigationFrame 的情況下使用該服務(wù)——因?yàn)樗呀?jīng)在主視圖級別進(jìn)行了配置。
并非所有DevExpress 服務(wù)都需要可視化組件,某些服務(wù),例如 或 ,不需要顯式附加,因此您可以將它們作為任何其他非 DevExpress 服務(wù)注入。
在某些情況下,如果需要為特定視圖配置服務(wù),則使用 DI 容器注入服務(wù)可能并不明智。 例如,如果您有一個綁定到視圖模型命令的服務(wù),就會出現(xiàn)這種情況,直接在視圖中定義服務(wù)并在那里配置所有綁定要容易得多。
DevExpress WPF擁有120+個控件和庫,將幫助您交付滿足甚至超出企業(yè)需求的高性能業(yè)務(wù)應(yīng)用程序。通過DevExpress WPF能創(chuàng)建有著強(qiáng)大互動功能的XAML基礎(chǔ)應(yīng)用程序,這些應(yīng)用程序?qū)W⒂诋?dāng)代客戶的需求和構(gòu)建未來新一代支持觸摸的解決方案。 無論是Office辦公軟件的衍伸產(chǎn)品,還是以數(shù)據(jù)為中心的商業(yè)智能產(chǎn)品,都能通過DevExpress WPF控件來實(shí)現(xiàn)。
DevExpress技術(shù)交流群6:600715373 歡迎一起進(jìn)群討論
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@ke049m.cn
文章轉(zhuǎn)載自:慧都網(wǎng)