2016-05-12 42 views
-1

我開發一個C#之前創建/ WPF/MVVM/UWP應用程序,它使用了ViewModelLocator它看起來像這樣:確保一個靜態類是在其他

public class ViewModelLocator 
{ 
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", 
     "CA1822:MarkMembersAsStatic", 
     Justification = "This non-static member is needed for data binding purposes.")] 
    public MainPageViewModel MainPage 
    { 
     get 
     { 
      return ServiceLocator.Current.GetInstance<MainPageViewModel>(); 
     } 
    } 


    static ViewModelLocator() 
    { 
     // DEBUG LINE: var test = Views.ViewLocator.MainPageKey; 
     ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); 

     if (ViewModelBase.IsInDesignModeStatic) 
     { 
      SimpleIoc.Default.Register<IDataService, Design.DesignDataService>(); 
     } 
     else 
     { 
      SimpleIoc.Default.Register<IDataService, DataService>(); 
     } 

     SimpleIoc.Default.Register<MainPageViewModel>(); 
    } 
} 

我有另一個類,一個ViewLocator,用於導航目的,看起來像這樣:

public class ViewLocator 
{ 
    public static readonly string MainPageKey = typeof(MainPage).Name; 
    public static readonly string WorkPageKey = typeof(WorkPage).Name; 

    static ViewLocator() 
    { 
     ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); 

     var navigationService = new NavigationService(); 

     navigationService.Configure(MainPageKey, typeof(MainPage)); 
     navigationService.Configure(WorkPageKey, typeof(WorkPage)); 

     SimpleIoc.Default.Register<INavigationService>(() => navigationService); 

     SimpleIoc.Default.Register<IDialogService, DialogService>(); 
    } 
} 

之前,這兩個類是在ViewModelLocator合併,但我想通了ViewModelLocator作爲「的ViewModels端 - 的 - 事」部分應該是不知道的意見和它是類型,這就是爲什麼我將該代碼重構爲兩個類。

我MainPageView然後有一個按鈕,這在MainPageView.cs

public class MainPageViewModel : ViewModelBase 
{ 
    private INavigationService _navigationService; 

    public RelayCommand CreateNewImageCommand { get; private set; } 

    public MainPageViewModel(INavigationService navigationService) 
    { 
     _navigationService = navigationService; 

     CreateNewImageCommand = new RelayCommand(CreateNewImage,() => true); 
    } 

    public void CreateNewImage() 
    { 
     _navigationService.NavigateTo(Views.ViewLocator.WorkPageKey); 
    } 
} 

爲了完整觸發導航命令,這裏是我的App.xaml

<Application 
...> 

<Application.Resources> 
    <v:ViewLocator x:Key="ViewLocator" /> 
    <vm:ViewModelLocator x:Key="ViewModelLocator" /> 
</Application.Resources> 

現在什麼碰巧是這樣的:如果我沒有在ViewModelLocator中的DEBUG LINE,在MainPage從ViewModelLocator請求它的ViewModel時,ViewLocator的構造函數尚未被調用,並且return ServiceLocator.Current.GetInstance<MainPageViewModel>();引發異常。如果我包含DEBUG LINE,這會強制ViewLocator構造函數首先運行,並且一切正常。

如何在沒有奇怪的調試行的情況下實現這種行爲?

+0

我只是要離開這裏[是ServiceLocator反模式](http://stackoverflow.com/questions/22795459/is-servicelocator-anti-pattern) – Liam

+0

TL; DR你應該真的使用依賴注入不服務定位器模式。通常如果從頭開始,這是一個更好,更容易理解的模式。 – Liam

+0

@Liam我不是IoC容器或ServiceLocator的粉絲,也不是你想要調用它的任何東西。這只是我一直在研究如何正確分離虛擬機和V,這是迄今爲止唯一令我滿意的工作方法。然而,我非常願意使用DI - 如果您可以請給我看一些正確使用它的參考代碼。 – Xaser

回答

0

您正遇到大多數開發人員不使用靜態類和服務定位器的原因。

正如您的意見建議嘗試使用依賴注入。這允許對管理該佈線的組件進行控制反轉。

將MEF或Unity看作是使用而不是滾動自己的IoC的框架。兩者都有優點和缺點,但要麼會奏效。他們還允許更簡單和更清潔的測試。

MEF

Unity

0

儘管所有的評論和其他答案,我認爲我是在賽道上畢竟。爲了解決這個問題,我創建了應用程序啓動時添加的SimpleIoC容器引導程序,並將代碼從ViewLocator的構造函數中移出。

我還刪除了ServiceLocator調用,這有點多餘,現在直接依賴SimpleIoC.Default

導航器仍然被SimpleIoC容器注入到ViewModels中。然而,ViewModelLocator必須與XAML代碼結合使用。

我推薦這個答案作爲其他人也在努力解決這個問題的出發點。

https://stackoverflow.com/a/25524753/2175012

畢竟,我已經採取了ServiceLocators沒有反模式,但必須謹慎使用的一面。

相關問題