wpf - Do I need to use DI and IoC everytime ModelView uses Model in MVVM? -


i'm new .net mvvm structure of application , have basic knowledge of it's principles, decoupling, bindings, commands , etc. i'm using mvvm light framework simplify common mvvm issues messaging , service location.

one thing don't understand: need call simpleioc every time using model classes viewmodel? example: have simple view, viewmodel corresponding , model 1 class settings.

mainwindow.xaml

<window ...>     <window.resources>         <viewmodels:mainwindowmodel x:key="viewmodel" />     </window.resources>     <dockpanel datacontext="{staticresource viewmodel}">         <button command="{binding dosomecommand}" />     </dockpanel> </window> 

mainwindowmodel.cs

public class mainwindowmodel: inotifypropertychanged {     public event propertychangedeventhandler propertychanged;     public icommand dosomecommand { get; private set; }      protected void raisepropertychangedevent(string propertyname)     {         propertychanged?.invoke(this, new propertychangedeventargs(propertyname));     }      public mainwindowmodel()     {         dosomecommand = new relaycommand(dosome);     }      public void dosome()     {         var data = settings.instance;  //singleton          //... data ...          debug.log($"{data.prop1}, {data.prop2}, {data.prop3}");     } } 

settings.cs

public static class settings  {     //... singleton implementations ...      public int prop1 { get; set; } // implementation of getters , setters             public int prop2 { get; set; }      public int prop3 { get; set; }   } 

this code has 1 huge disadvantage: dosome() method not unit-testable. ok, let's fix that:

public class mainwindowmodel: inotifypropertychanged {      //...      private settings _data;       public mainwindowmodel()       {           _data = settings.instance;           dosomecommand = new relaycommand(() => dosome(_data));      }       public void dosome(settings data)      {            //... data ...           debug.log($"{data.prop1}, {data.prop2}, {data.prop3}");      } } 

now can mock or stub settings class , test dosome().


but know 'settings' class in different implementations, 'settingsxml' (data xml), 'settingsregistry' (data window registry), 'settingsini' (data ini-file, wierd, true). avoid potential problems rewrote in interfaces:

public interface isettings {     public int prop1;     public int prop2;     public int prop3; }   public static class settings: isettings  {     //... singleton implementations ...      public int prop1 { get; set; } // implementation of getters , setters             public int prop2 { get; set; }      public int prop3 { get; set; }   }  public class mainwindowmodel: inotifypropertychanged {      //...      private isettings _data;       public void dosome(isettings data)      {            ... data ...           debug.log($"_data.prop1}, {data.prop2}, {data.prop3}");      }  } 

everything looks fine me. dosome() testable , settings implementation different. 1 thing bothers me: mainwindowmodel knows actual class of settings (_data = settings.instance).

is ok in mvvm structure?

is necessary use ioc, write 'settingswrapper' class dependency injection of isettings class , use _data = simpleioc.default.getinstance<settingswrapper>?

what should if settings class not singleton?

sorry, if got basic idea of di , ioc wrong. appreciate, if correct me.

one thing bothers me: mainwindowmodel knows actual class of settings (_data = settings.instance).

it shouldn't. should know interface getting injecting with.

instead of passing isettings object dosome method, inject mainwindowmodel class isettings when create it:

public mainwindowmodel(isettings settings) { ... } 

you let viewmodellocator taking care of creating view model class:

public class viewmodellocator {     public viewmodellocator()     {         servicelocator.setlocatorprovider(() => simpleioc.default);          simpleioc.default.register<isettings>(() => settings.instance);         simpleioc.default.register<mainviewmodel>();     }      public mainviewmodel main     {                 {             return servicelocator.current.getinstance<mainviewmodel>();         }     } } 

<dockpanel datacontext="{binding main, source={staticresource locator}}">     <button command="{binding dosomecommand}" /> </dockpanel> 

Comments

Popular posts from this blog

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

python Tkinter Capturing keyboard events save as one single string -

sql server - Why does Linq-to-SQL add unnecessary COUNT()? -