2016-04-27 64 views
1

這一個有點複雜,所以請閱讀所有內容。我正在研究一些爲WPF實現MVVM模式的代碼。我有一個XAML標記擴展,它在datacontext上查找特定的屬性。 (這是一個漫長而有趣的故事,但超出了範圍)我的視圖模型將被設置爲視圖上的Dataconext。繼承依賴注入簡化

這裏有一個如何我已經實現了我的BaseViewmodel一個例子...

public class ViewModelBase : IViewModelBase 
{ 
    protected CommandManagerHelper _commandManagerHelper; 

    //todo find a way of eliminating the need for this constructor 
    public OrionViewModelBase(CommandManagerHelper commandManagerHelper) 
    { 
     _commandManagerHelper = commandManagerHelper; 
    } 

    private IExampleService _exampleService; 

    public IExampleService ExampleService 
    { 
     get 
     { 
      if (_exampleService == null) 
      { 
       _exampleService = _commandManagerHelper.GetExampleService(); 
      } 

      return _exampleService; 
     } 
    } 
} 

發生了什麼事有,我很有效地延遲加載的_exampleService。我相信可以使用Lazy,但我還沒有完全實現。

我的Xaml標記將尋找和使用我的ExampleService它也可以被視圖模型中的代碼使用。它將在整個應用程序中使用。

需要注意的是,我的應用程序將只有一個ExampleServer實例將被傳遞,從應用程序中的任何位置調用GetExampleService將返回該對象的相同實例。只有一個ExampleService對象的實例,儘管它沒有被編碼爲單例。

這裏是我如何從我的ViewModelBase繼承的例子...

internal class ReportingViewmodel : ViewModelBase 
{ 
    private readonly IReportingRepository _reportingRepository; 

    public ReportingViewmodel(CommandManagerHelper commandManagerHelper, IReportingRepository reportingRepository) : base(commandManagerHelper) 
    { 
     _reportingRepository = reportingRepository; 
    } 
} 

此代碼的工作和偉大工程。但是,每次我實現ViewModelBase的新繼承成員時,都必須鍵入「:base(commandManagerHelper)」,這很容易出錯。我可能有100個這樣的實現,每個都需要是正確的。

我想知道的是....是否有一種方法實現相同的行爲尊重固體原則,而不必每次我實現ViewModelBase實例時調用基礎構造函數?

即我想要ReportingViewModel看起來像這樣

internal class ReportingViewmodel : ViewModelBase 
{ 
    private readonly IReportingRepository _reportingRepository; 

    public ReportingViewmodel(IReportingRepository reportingRepository) 
    { 
     _reportingRepository = reportingRepository; 
    } 
} 

,但仍然有ExampleService無誤。

我目前正在考慮使用服務定位器模式,我也在考慮使用Singleton,並且我願意接受其他更好的解決方案。

我問這個問題而不是潛入代碼的原因是我知道Singleton通常是反模式,對我來說它表示代碼中有其他錯誤。 我剛剛閱讀了關於IoC的一篇文章,並在此處討論了服務定位器模式,文章http://www.devtrends.co.uk/blog/how-not-to-do-dependency-injection-the-static-or-singleton-container

回答

2

你不能退出調用基構造函數。 IExampleService只實例化一次並共享並不重要。你的ViewModelBase沒有(也不應該)「知道」。所有它需要知道的是,無論是注入實現該接口。 這是一個很大的好處,因爲當你單元測試類時,你可以注入一個模擬版本的接口。如果類依賴於對基類中某些東西的靜態引用,那麼就不可能用模擬來替換它來進行測試。我使用ReSharper。 (我是否允許這麼說呢?我不打算做廣告。)在許多其他事情中,它會爲您生成這些基礎構造函數。我確信在某些時候需要內置到Visual Studio中。

+0

我也使用ReSharper。 :D我正在尋找這個解決方案的最佳實施。 –

+0

我想這個問題還有另一部分。我有一個使用我的自定義標記擴展的視圖,並且必須設置視圖datacontext,即使視圖並不真正需要視圖模型(這是一個簡單的顯示對話框)標記需要了解IExampleService,而不是視圖。創建一個完整的視圖模型仍然是正確的嗎?或者它可以讓標記從別處拉出擴展名嗎? (如果沒關係意味着我可以改變視圖模型的組成方式)只需要弄清楚如何去做。 –

+0

經過反思,我認爲關於讓標記擴展工作而不使用視圖模型的問題是另一個話題。 –