第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在WPF / MVVM應用程序中處理依賴項注入

如何在WPF / MVVM應用程序中處理依賴項注入

慕雪6442864 2019-11-07 12:47:59
我正在啟動一個新的桌面應用程序,我想使用MVVM和WPF來構(gòu)建它。我也打算使用TDD。問題是我不知道如何使用IoC容器將依賴項注入生產(chǎn)代碼中。假設我有以下類和接口:public interface IStorage{    bool SaveFile(string content);}public class Storage : IStorage{    public bool SaveFile(string content){        // Saves the file using StreamWriter    }}然后我有另一個具有IStorage依賴關系的類,還假設該類是ViewModel或業(yè)務類...public class SomeViewModel{    private IStorage _storage;    public SomeViewModel(IStorage storage){        _storage = storage;    }}有了這個,我可以輕松地編寫單元測試,以確保它們能夠正常工作,例如使用模擬等。問題是要在實際應用程序中使用它。我知道我必須有一個IoC容器,該容器鏈接了該IStorage接口的默認實現(xiàn),但是我該怎么做呢?例如,如果我具有以下xaml,將如何處理:<Window     ... xmlns definitions ...>   <Window.DataContext>        <local:SomeViewModel />   </Window.DataContext></Window>在這種情況下,如何正確地“告訴” WPF以注入依賴關系?另外,假設我需要的實例SomeViewModel從我的cs代碼,我應該怎么辦呢?我感到自己完全迷失了這一點,對于任何如何處理最佳方法的示例或指導,我將不勝感激。我熟悉StructureMap,但我不是專家。另外,如果有更好/更輕松/開箱即用的框架,請告訴我。提前致謝。
查看完整描述

3 回答

?
偶然的你

TA貢獻1841條經(jīng)驗 獲得超3個贊

我一直在使用Ninject,發(fā)現(xiàn)與我合作很愉快。一切都在代碼中設置,語法非常簡單,并且有一個很好的文檔。


所以基本上它是這樣的:


創(chuàng)建視圖模型,并將IStorage接口作為構(gòu)造函數(shù)參數(shù):


class UserControlViewModel

{

? ? public UserControlViewModel(IStorage storage)

? ? {


? ? }

}

使用視圖屬性的get屬性創(chuàng)建一個ViewModelLocator,該模型從Ninject加載視圖模型:


class ViewModelLocator

{

? ? public UserControlViewModel UserControlViewModel

? ? {

? ? ? ? get { return IocKernel.Get<UserControlViewModel>();} // Loading UserControlViewModel will automatically load the binding for IStorage

? ? }

}

在App.xaml中使ViewModelLocator成為應用程序范圍的資源:


<Application ...>

? ? <Application.Resources>

? ? ? ? <local:ViewModelLocator x:Key="ViewModelLocator"/>

? ? </Application.Resources>

</Application>

將UserControl的DataContext綁定到ViewModelLocator中的相應屬性。


<UserControl ...

? ? ? ? ? ? ?DataContext="{Binding UserControlViewModel, Source={StaticResource ViewModelLocator}}">

? ? <Grid>

? ? </Grid>

</UserControl>

創(chuàng)建一個繼承NinjectModule的類,該類將設置必要的綁定(IStorage和viewmodel):


class IocConfiguration : NinjectModule

{

? ? public override void Load()

? ? {

? ? ? ? Bind<IStorage>().To<Storage>().InSingletonScope(); // Reuse same storage every time


? ? ? ? Bind<UserControlViewModel>().ToSelf().InTransientScope(); // Create new instance every time

? ? }

}

在應用程序啟動時使用必要的Ninject模塊(目前上面的模塊)初始化IoC內(nèi)核:


public partial class App : Application

{? ? ? ?

? ? protected override void OnStartup(StartupEventArgs e)

? ? {

? ? ? ? IocKernel.Initialize(new IocConfiguration());


? ? ? ? base.OnStartup(e);

? ? }

}

我使用了靜態(tài)IocKernel類來保存IoC內(nèi)核的應用程序范圍的實例,因此可以在需要時輕松訪問它:


public static class IocKernel

{

? ? private static StandardKernel _kernel;


? ? public static T Get<T>()

? ? {

? ? ? ? return _kernel.Get<T>();

? ? }


? ? public static void Initialize(params INinjectModule[] modules)

? ? {

? ? ? ? if (_kernel == null)

? ? ? ? {

? ? ? ? ? ? _kernel = new StandardKernel(modules);

? ? ? ? }

? ? }

}

此解決方案確實使用了靜態(tài)ServiceLocator(IocKernel),通常將其視為反模式,因為它隱藏了類的依賴項。但是,避免對UI類進行某種形式的手動服務查找非常困難,因為它們必須具有無參數(shù)的構(gòu)造函數(shù),而且您無論如何也無法控制實例化,因此無法注入VM。至少通過這種方式,您可以隔離地測試VM,這是所有業(yè)務邏輯所在的位置。


查看完整回答
反對 回復 2019-11-07
?
飲歌長嘯

TA貢獻1951條經(jīng)驗 獲得超3個贊

在您的問題中,您設置了DataContextXAML中視圖屬性的值。這要求您的視圖模型具有默認的構(gòu)造函數(shù)。但是,正如您已經(jīng)指出的那樣,這與要在構(gòu)造函數(shù)中注入依賴項的依賴項注入不能很好地配合。


因此,您無法DataContext在XAML中設置屬性。相反,您還有其他選擇。


如果您的應用程序基于簡單的分層視圖模型,則可以在應用程序啟動時構(gòu)造整個視圖模型分層結(jié)構(gòu)(您必須StartupUri從App.xaml文件中刪除屬性):


public partial class App {


  protected override void OnStartup(StartupEventArgs e) {

    base.OnStartup(e);

    var container = CreateContainer();

    var viewModel = container.Resolve<RootViewModel>();

    var window = new MainWindow { DataContext = viewModel };

    window.Show();

  }


}

這基于植根于的視圖模型的對象圖,RootViewModel但是您可以將一些視圖模型工廠注入父視圖模型,從而允許它們創(chuàng)建新的子視圖模型,因此不必固定對象圖。這也希望回答您的問題想我需要的實例,SomeViewModel從我的cs代碼,我應該怎么辦呢?


class ParentViewModel {


  public ParentViewModel(ChildViewModelFactory childViewModelFactory) {

    _childViewModelFactory = childViewModelFactory;

  }


  public void AddChild() {

    Children.Add(_childViewModelFactory.Create());

  }


  ObservableCollection<ChildViewModel> Children { get; private set; }


 }


class ChildViewModelFactory {


  public ChildViewModelFactory(/* ChildViewModel dependencies */) {

    // Store dependencies.

  }


  public ChildViewModel Create() {

    return new ChildViewModel(/* Use stored dependencies */);

  }


}

如果您的應用程序本質(zhì)上更具動態(tài)性,并且可能是基于導航的,那么您將不得不加入執(zhí)行導航的代碼。每次導航到新視圖時,都需要創(chuàng)建一個視圖模型(從DI容器中),視圖本身并將DataContext該視圖的設置為該視圖模型。您可以先執(zhí)行此視圖,然后再根據(jù)視圖選擇視圖模型,也可以先執(zhí)行視圖模型視圖模型確定使用哪個視圖。MVVM框架通過某種方式提供了此關鍵功能,您可以將DI容器掛接到視圖模型的創(chuàng)建中,但也可以自己實現(xiàn)。我在這里有點含糊,因為根據(jù)您的需要,此功能可能會變得非常復雜。這是您從MVVM框架獲得的核心功能之一,但是在簡單的應用程序中滾動自己的功能將使您很好地了解MVVM框架提供的功能。


由于無法DataContext在XAML中聲明,因此失去了一些設計時支持。如果您的視圖模型包含一些數(shù)據(jù),它將在設計時出現(xiàn),這可能非常有用。幸運的是,您也可以在WPF中使用設計時屬性。一種方法是將以下屬性添加到<Window>元素或<UserControl>XAML中:


xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

mc:Ignorable="d"

d:DataContext="{d:DesignInstance Type=local:MyViewModel, IsDesignTimeCreatable=True}"

視圖模型類型應具有兩個構(gòu)造函數(shù),默認構(gòu)造函數(shù)用于設計時數(shù)據(jù),另一個構(gòu)造函數(shù)用于依賴項注入:


class MyViewModel : INotifyPropertyChanged {


  public MyViewModel() {

    // Create some design-time data.

  }


  public MyViewModel(/* Dependencies */) {

    // Store dependencies.

  }


}

這樣,您可以使用依賴項注入并保留良好的設計時支持。


查看完整回答
反對 回復 2019-11-07
  • 3 回答
  • 0 關注
  • 1119 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網(wǎng)微信公眾號