2011-03-02 113 views
4

時,我有一個傳統的MVVM的做法,因此,例如一個名爲是利用一種被稱爲「PatientManagementView」視圖「PatientManagementViewModel」視圖模型。一切都是使用MEF注入的,所以我不會自己創建任何實例。創建子視圖模型使用MEF

現在假設「PatientManagementViewModel」有一個屬性的患者,這是「PatientViewModel」的ObervableCollection。我現在做的打造「PatientViewModel」的一個實例,並通過所選擇的病人是這樣的:

var patientViewModel = _container.GetExportedValue<IPatientViewModel>(); 
patientViewModel.Patient = patient; 

這工作,不過,我想知道,這是有道理的。這將是更好的給患者傳遞給構造函數,因爲「PatientViewModel」不能沒有病人存在:

var patientViewModel = new PatientViewModel(patient); 

但我不能使用依賴注入。

所以現在的問題是:它是有意義的注入subviewmodel,或者我應該只注入主視圖模型,並實例所有subviewmodels沒有注入?

+0

‘PatientManagementViewModel’有一個屬性的患者,這是一個ObervableCollection‘PatientViewModel’<=我認爲你應該重新考慮你的應用程序設計。 – Tokk 2011-03-02 12:25:18

+3

你能解釋一下嗎?我看不出有什麼問題。 – 2011-03-02 13:18:45

回答

1

你可以做到以下幾點。你可以用通常的構造方法來創建你的孩子視圖模型,然後調用ComposeParts上的實例注入的一切:

var patientViewModel = new PatientViewModel(patient); 
_container.ComposeParts(patientViewModel); 

但是這每一次這樣做是不是爲了各種各樣的原因非常好。爲了解決這種情況並封裝MEF的使用,我創建了一個幫助器服務來創建視圖模型。這就是所謂的IViewModelFactory,這裏是它的外觀:

[Export(typeof(IViewModelFactory))] 
[PartCreationPolicy(CreationPolicy.Shared)] 
internal class ViewModelFactory : IViewModelFactory 
{ 
    [ImportingConstructor] 
    public ViewModelFactory(CompositionContainer container) { 
     Contract.Requires(container != null); 

     Container = container; 
    } 

    protected CompositionContainer Container { get; private set; } 

    public T Create<T>(params object[] args) where T : class { 
     T result; 

     try { 
      bool populateDependencies = false; 

      if (args == null || args.Length == 0) { 
       // There are no parameters for contructor, so 
       // try to create an instance by asking the container. 
       result = Container.GetExportedValueOrDefault<T>(); 

       if (result == null) { 
        // The view model is not exported. Just create an instance using reflection 
        // and then populate all the dependencied using the container. 
        result = Activator.CreateInstance<T>(); 
        populateDependencies = true; 
       } 
      } 
      else { 
       // There are constructor parameters. Create an instance using those parameters 
       // and then populate all the dependencied using the container. 
       result = (T)Activator.CreateInstance(typeof(T), args); 
       populateDependencies = true; 
      } 

      // Populate dependencies if needed 
      if (populateDependencies) { 
       Container.ComposeParts(result); 
      } 

      // Initialize the object if applicable 
      var initializable = result as IInitializable; 

      if (initializable != null) { 
       initializable.Initialize(); 
      } 
     } 
     catch (Exception ex) { 

      throw new ViewModelCreationException(
       string.Format(
        "Unable to create and configure an instance of view model of type {0}. An error occured. See inner exception for details.", 
        typeof (T)), ex); 
     } 

     return result; 
    } 
} 

使用此工廠可以創建子視圖模式是這樣的:

var patientViewModel = ViewModelFactory.Create<PatientViewModel>(patient); 

這裏的缺點是,當你使用構造函數的參數,你對於參數寬鬆的編譯時檢查類型,計數,責令等

+0

我喜歡這個解決方案,非常感謝你! – 2011-03-02 14:47:11

+0

ExportFactory會使這個更清潔。它不是在MEF的.NET 4版本中支持,但未來版本將擁有它,而CodePlex上預覽版和Silverlight已經擁有它。 – 2011-03-03 15:51:29

+0

@Daniel - 有趣的...你能提供一個鏈接? – 2011-03-03 16:54:54