Take a simple example - the base of cities. Let's make an interface of the city handler, which, in particular, should save information about the city. It turns out something like this:
interface ICitiesHandler { Save(City city); ... }
And somewhere we describe its implementation (it does not interest us). Registered it in a DI-container. I am using MVVMLight
. When added to a project, he creates such a class (in which we register our handler):
public class ViewModelLocator { static ViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); if (ViewModelBase.IsInDesignModeStatic) { // Create design time view services and models //SimpleIoc.Default.Register<IDataService, DesignDataService>(); } else { SimpleIoc.Default.Register<ICitiesHandler, CitiesHandler>(); // Регистрируем обработчик } } /// <summary> /// Initializes a new instance of the ViewModelLocator class. /// </summary> public ViewModelLocator() { } public static void Cleanup() { // TODO Clear the ViewModels } }
}
Further we will make ViewModel
city. Its dependency will be our ICitiesHandler
- it must accept the changes from the user and save them.
class CityVM : BaseVM { private readonly ICitiesHandler _handler; private readonly City _city; public CityVM(City city, ICitiesHandler handler) { } ... public void Save() { // Применение изменений ... Save(_city); } }
It seems everything is done. But now in some of the code sections I need to create a new city. And all is well, if I have an instance of the ICitiesHandler
implementation, but do not pass it as a dependency on all the objects that cities can create? In theory, I would like to do this:
var city = new CityVM(); // Далее наполняем данными и сохраняем ... city.Save();
For this, for CityVM
I can make a default constructor, in which I can transfer new City()
as a city model, but how can I resolve the ICitiesHandler
dependency?
public CityVM() : base(new City(), ???) { }
How to be? I have two options.
All VMs should be requested from the DI container, but then the entire
ViewModel
layer will refer toServiceLocator
, even if it is a static class, even a singleton (which, by the way, some people also consider antipattern, along withServiceLocator
)Or all the functionality for resolving dependencies should be concluded in one place, to which all
ViewModel
have access - this isBaseVM
. We make it aResolve<T>()
method and then the designer of the newCityVM
will look like this:public CityVM() : base(new City(), Resolve<ICitiesHandler>())
Which is also not very pleasant to me, because we hide the dependence on the programmer
In the book by Mark Siman “Dependency Injection in .NET” he says that SerciceLocator
can be used, but carefully. At the same time, encapsulate it as close as possible to the CompositionRoot
.
How to be? What am I doing wrong? Or am I using the wrong framework for this?
ICitiesHandler
as a dependency to all objects that can create cities as a problem? 2. Why do you needICitiesHandler
when creating a new city? You do not need to save the city in the database immediately after its creation? Instead, you can create a separate interface-factory, which is taken as dependency in all places where you need to create cities. - Dmitry ShevchenkoICitiesHandler
throughout the chain. Doubtful perspective. 2. I did not understand. I need to call theSave
method so that this entry is created.ICitiesHandler
willICitiesHandler
immediately in the database or not, I should not be interested in what is happening under the hood of the specific implementation ofICitiesHandler
not a problem in this context - Donil