天天看點

MVVM模式之:ViewModel Factory與注入

基于以下的理由,ViewModel也是需要多個,并且需要被注入的:

1:設計時和運作時需要為View提供不同的資料

簡單來說,就是設計時需要模拟資料。界面設計開發人員需要進行綁定(包括支援Expression Blend綁定)做一些簡單的處理,同時因為提供了模拟資料,UI人員可以更好的設計實際的界面。

2:為了友善單元測試

在運作時,大部分情況下,ViewModel會組合進提供Service的業務類。在簡單的應用中,我們可以注入Service類的MOCK來進行單元測試,如果是這樣,就可以避免提供多個ViewModel。但在有些應用中,如Silverlight應用中,服務由WerbService、WCF提供,就無法讓用戶端應用服務所支援的接口類,并且用戶端的代碼都是自動生成的,這樣我們就需要提供多個ViewModel來支援單元測試。

3:為設計時提供模拟資料

考慮到VM需要存在多個,是以UI的VM需要存在一個基類,假設我的UI需要顯示一個學生的清單,那麼我的VM基類設計如下:

public class MainPageVmBase
    {
        public MainPageVmBase()
        {
            click = new DelegateCommand(OnClick);
        }

        public IStudent StudentService { get; set; }
        public IView View { get; set; }

        private ICommand click;

        public ICommand Click
        {
            get { return click; }
            set { click = value; }
        }

        void OnClick(object arg)
        {
            View.Title = arg as string;
            View.Show();
        }

        private List<Student> studets;

        public List<Student> Studets
        {
            get { return studets; }
            set { studets = value; }
        }
    }      

設計時的VM需要提供模拟資料,那麼該VM為:

public class MainPageVmMock : MainPageVmBase
    {
        public MainPageVmMock()
        {
            Studets = new List<Student>()
                              {
                                  new Student() {Name = "d1", Age = 11},
                                  new Student() {Name = "d2", Age = 22}
                              };
        }
    }      

要讓設計時顯式模拟資料,我們需要用到一個DesignHelpers類(該類來自于

https://github.com/jeremiahredekop/

):

public static class DesignHelpers
    {
        private static bool? _designMode;
        public static bool DesignMode
        {
            get
            {
                if (!_designMode.HasValue)
                {
#if !SILVERLIGHT
                    _designMode = new bool?(DesignerProperties.GetIsInDesignMode(new System.Windows.DependencyObject()));
#else
                    _isInDesignMode = new bool?(DesignerProperties.IsInDesignTool);
#endif
                }
                return _designMode.Value;
            }
        }
    }      

借助于這個類的處理,這個時候我們在Expression Blend進行綁定的時候,就可以顯式我們的模拟資料:

MVVM模式之:ViewModel Factory與注入

4:ViewModel FACTORY

每個UI綁定的VM實際都來自于VM FACTORY的類,如上面這個頁面,我們綁定的就是MainPageVmFactory中的ViewModel屬性。每個VmFactory也有自己的基類,如下:

public class ViewModelFactory<TViewModelRealBase>
        where TViewModelRealBase : class, new()
    {
        public TViewModelRealBase ViewModel
        {
            get;
            set;
        }
    }      

MainPageVmFactory如下:

public class MainPageVmFactory : ViewModelFactory<MainPageVmBase>
    {
        public MainPageVmFactory()
        {
            if (DesignHelpers.DesignMode == true)
            {
                this.ViewModel = new MainPageVmMock();
            }
            else
            {
                using (IUnityContainer container = new UnityContainer())
                {
                    var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
                    section.Configure(container, "containerOne");
                    this.ViewModel = container.Resolve<MainPageVmBase>("MainPageVmReal");
                }
            }
        }
    }      

可以看到,運作時的VM我們通過unity注入的方式來得到,本文一開頭已經說過了,之是以采用注入方式是為了單元測試友善。注入的是MainPageVmReal這個類型,它包含有實際提供資料的服務類,如下:

public class MainPageVmReal : MainPageVmBase
    {
        public MainPageVmReal()
        {
            //Studets = new List<Student>()
            //                  {
            //                      new Student() {Name = "r1", Age = 11},
            //                      new Student() {Name = "r2", Age = 22}
            //                  };
            using (IUnityContainer container = new UnityContainer())
            {
                UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
                section.Configure(container, "containerOne");
                IStudent service = container.Resolve<IStudent>("StudentService");
                Studets = service.GetAllStudent() as List<Student>;
            }
        }
    }      

MainPageVmReal中實際提供資料的服務類,可以是WCF的用戶端代碼,或者是任何别的東西,這裡不是我們關注的重點,是以我們可以不用去管裡面的那段注入代碼。

運作時結果:

MVVM模式之:ViewModel Factory與注入

5:關于注入

注入這部分就很容易了解了,在配置處寫入我們實際需要VM類型就可以了:

MVVM模式之:ViewModel Factory與注入

整體代碼下載下傳:

WpfApplication20110811.rar
MVVM模式之:ViewModel Factory與注入

本文基于

Creative Commons Attribution 2.5 China Mainland License

釋出,歡迎轉載,演繹或用于商業目的,但是必須保留本文的署名

http://www.cnblogs.com/luminji

(包含連結)。如您有任何疑問或者授權方面的協商,請給我留言。

繼續閱讀