2010-03-25 60 views
2

我剛學與MEF MVVM並且已經看到了好處,但我有點困惑的一些實施細節的通用接口。我正在構建的應用程序有幾個與不同實體(WCF RIA Services公開實體框架對象)相同的模型,我希望避免爲每個需要的視圖實現類似的界面/模型,以下是我所擁有的拿出來雖然目前不起作用。重構多個接口使用MVVM,MEF和Silverlight4

常見的接口具有實現基本模型中的每個模型的新完成的事件,這是我能實現一個共同的類,因爲編譯器不喜歡從孩子鑄造基類型的最簡單方法。

的代碼,因爲它目前是編譯和運行,但是在通入[ImportingConstructor]爲FaqViewModel類空IModel。

我有如下定義,這應該熟悉那些誰見過肖恩Wildermuth的RIAXboxGames樣品的通用接口(簡化發佈)。

public interface IModel 
{ 
    void GetItemsAsync(); 
    event EventHandler<EntityResultsArgs<faq>> GetFaqsComplete; 
} 

實現接口甲基方法

public class ModelBase : IModel 
{ 
    public virtual void GetItemsAsync() { } 
    public virtual event EventHandler<EntityResultsArgs<faq>> GetFaqsComplete; 
    protected void PerformQuery<T>(EntityQuery<T> qry, EventHandler<EntityResultsArgs<T>> evt) where T : Entity 
    { 
     Context.Load(qry, r => 
     { 
      if (evt == null) return; 
      try 
      { 
       if (r.HasError) 
       { 
        evt(this, new EntityResultsArgs<T>(r.Error)); 
       } 
       else if (r.Entities.Count() > 0) 
       { 
        evt(this, new EntityResultsArgs<T>(r.Entities)); 
       } 
      } 
      catch (Exception ex) 
      { 
       evt(this, new EntityResultsArgs<T>(ex)); 
      } 
     }, null); 
    } 

    private DomainContext _domainContext; 
    protected DomainContext Context 
    { 
     get 
     { 
      if (_domainContext == null) 
      { 
       _domainContext = new DomainContext(); 
       _domainContext.PropertyChanged += DomainContext_PropertyChanged; 
      } 

      return _domainContext; 
     } 
    } 

    void DomainContext_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 
    { 
     switch (e.PropertyName) 
     { 
      case "IsLoading": 
       AppMessages.IsBusyMessage.Send(_domainContext.IsLoading); 
       break; 
      case "IsSubmitting": 
       AppMessages.IsBusyMessage.Send(_domainContext.IsSubmitting); 
       break; 
     } 
    } 
} 

實現該基本模型

[Export(ViewModelTypes.FaqViewModel, typeof(IModel))] 
public class FaqModel : ModelBase 
{ 
    public override void GetItemsAsync() 
    { 
     PerformQuery(Context.GetFaqsQuery(), GetFaqsComplete); 
    } 

    public override event EventHandler<EntityResultsArgs<faq>> GetFaqsComplete; 
} 

視圖模型

[PartCreationPolicy(CreationPolicy.NonShared)] 
[Export(ViewModelTypes.FaqViewModel)] 
public class FaqViewModel : MyViewModelBase 
{ 
    private readonly IModel _model; 

    [ImportingConstructor] 
    public FaqViewModel(IModel model) 
    { 
     _model = model; 
     _model.GetFaqsComplete += Model_GetFaqsComplete; 

     _model.GetItemsAsync(); // Load FAQS on creation 
    } 

    private IEnumerable<faq> _faqs; 
    public IEnumerable<faq> Faqs 
    { 
     get { return _faqs; } 
     private set 
     { 
      if (value == _faqs) return; 

      _faqs = value; 
      RaisePropertyChanged("Faqs"); 
     } 
    } 

    private faq _currentFaq; 
    public faq CurrentFaq 
    { 
     get { return _currentFaq; } 
     set 
     { 
      if (value == _currentFaq) return; 

      _currentFaq = value; 
      RaisePropertyChanged("CurrentFaq"); 
     } 
    } 

    public void GetFaqsAsync() 
    { 
     _model.GetItemsAsync(); 
    } 

    void Model_GetFaqsComplete(object sender, EntityResultsArgs<faq> e) 
    { 
     if (e.Error != null) 
     { 
      ErrorMessage = e.Error.Message; 
     } 
     else 
     { 
      Faqs = e.Results; 
     } 
    } 
} 

然後終於Silverlight的模型查看本身

public partial class FrequentlyAskedQuestions 
{ 
    public FrequentlyAskedQuestions() 
    { 
     InitializeComponent(); 
     if (!ViewModelBase.IsInDesignModeStatic) 
     { 
      // Use MEF To load the View Model 
      CompositionInitializer.SatisfyImports(this); 
     } 
    } 

    [Import(ViewModelTypes.FaqViewModel)] 
    public object ViewModel 
    { 
     set 
     { 
      DataContext = value; 
     } 
    } 
} 

回答

0

看起來好像我正試圖重構成多個模型一樣走錯了路。如這裏所見,http://msdn.microsoft.com/en-us/magazine/dd458800.aspx#id0090019如果看起來最好的做法是將模型視爲通過RIA服務引用的EDMX類的實例。因此,該模型應該包含訪問DomainContext所需的所有方法和事件處理程序。

如果有人有其他的想法,我會向他們開放。

0

同樣作爲一個菜鳥,我剛開始使用MEF玩,我想我已經確定了可能的問題與您的代碼。從你的問題來看,這聽起來像你的主要問題是null IModel引用。

嘗試改變這一點:

private readonly IModel _model; 

這樣:

[Import] 
public IModel _model { get; set; } 

我還沒玩過MEF如何喜歡私人和只讀屬性,所以要儘量設置爲公共然後驗證_model在第一次嘗試使用它時不爲null。