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
ViewModellayer 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
ViewModelhave access - this isBaseVM. We make it aResolve<T>()method and then the designer of the newCityVMwill 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?
ICitiesHandleras a dependency to all objects that can create cities as a problem? 2. Why do you needICitiesHandlerwhen 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 ShevchenkoICitiesHandlerthroughout the chain. Doubtful perspective. 2. I did not understand. I need to call theSavemethod so that this entry is created.ICitiesHandlerwillICitiesHandlerimmediately in the database or not, I should not be interested in what is happening under the hood of the specific implementation ofICitiesHandlernot a problem in this context - Donil