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
Post a Comment