MVVMLight ViewModelLocator registering dataservice

This question may look naive, but I could not understand this code in the ViewModelLocator.cs file:

static ViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); if (ViewModelBase.IsInDesignModeStatic) { SimpleIoc.Default.Register<IDataService, Design.DesignDataService>(); } else { SimpleIoc.Default.Register<IDataService, DataService>(); } SimpleIoc.Default.Register<MainViewModel>(); } 

I see that we are using a DataService to get data (for example, from a WCF service) and assign it to MainViewModel. But what if I register more than one ViewModel? eg:

 static ViewModelLocator() { .... SimpleIoc.Default.Register<MainViewModel>(); SimpleIoc.Default.Register<Page2ViewModel>(); } 

and say that I have another DataService (e.g. DataService2), but I will use it with Page2ViewModel. How can i do this?

Also, if someone can help me (or even give me a reading link) about the above code. I have no idea what that means.

+7
source share
1 answer

Here you are not assigning an IDataService MainViewModel . You register type mappings, so your container will know that it should return a DataService when an IDataService is required.

This is due to dependency injection http://en.wikipedia.org/wiki/Dependency_injection

The DI container automatically connects the dependencies, so when you need a specific type, you can call

ServiceLocator.Current.GetInstance<IDataService>()

or

 ServiceLocator.Current.GetInstance<MainViewModel>() 

etc .. If he can build it (so that you register your types), he will allow you a complete dependency graph.

For example, if your MainViewModel has a constructor dependency on IDataService , and you are not in design mode, the DataService will be inserted into the MainViewModel constructor. Do not be afraid of the buzzword you just entered, it's just a call to the MainViewModel constructor with the appropriate parameters :).

So, MainViewModel here will not interfere with Page2ViewModel .

I made a simple example for you to demonstrate what is happening (I used Unity, http://unity.codeplex.com/ , but the syntax is pretty much the same):

 class Program { static void Main(string[] args) { var container = new UnityContainer(); container.RegisterType<IService, Service1>(); container.RegisterType<IService, Service2>("MySpecificService"); container.RegisterType<IRepository, Repository>(); ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container)); var viewModel = ServiceLocator.Current.GetInstance<MainViewModel>(); viewModel.Foo(); } } interface IService { } interface IRepository { } class Service1 : IService { public Service1(IRepository repository) { Console.WriteLine("Service1 created"); } } class Service2 : IService { public Service2() { Console.WriteLine("Service2 created"); } } class Repository : IRepository { public Repository() { Console.WriteLine("Repository created"); } } class MainViewModel { public MainViewModel(IService service) { Console.WriteLine("MainViewModel created"); } public void Foo() { var specificService = ServiceLocator.Current.GetInstance<IService>("MySpecificService"); } } 

output:

 Repository created Service1 created MainViewModel created Service2 created 

Since you need a MainViewModel (you may need to register a MainViewModel in SimpleIoC, it can resolve specific classes in Unity without matching), the container tries to create it, but it understands that the MainViewModel requires an IService , and it finds the default value from the mapping, which is Service1 , but it understands that Service1 needs an IRepository , and it finds the default value, so it can pass the Repository to Service1 , then an instance of Service1 in the MainViewModel constructor. All dependencies resolved.

The Foo call is an example of how you can register more than one type for the same interface. Injection dependence is a much more important topic, but automatic wiring is an important part of it.

+21
source

All Articles