"Service" is a general purpose abstraction, that allows you to isolate some portion of code from another parts of application.
Usually, in WPF/MVVM world, "service" consists of at least three items:
- service interface;
- one "real" service implementation, which does all the work;
- one "fake" service implementation for unit-testing purposes.
Service groups a bunch of related methods. There could be "dialog services" (show dialogs), "data services" (get data from data source, save data to data source), etc. You may think about "service" as of about the way to link your view models with outer world.
For example, WPF service, which purpose is to show some typical dialogs, will have interface like this:
public interface IDialogService
{
void ShowAboutBox(AboutBoxSettings settings);
MessageBoxResult ShowMessageBox(MessageBoxSettings settings);
bool? ShowSaveFileDialog(FileDialogSettings settings);
bool? ShowOpenFileDialog(FileDialogSettings settings);
}
Its "real" implementation will call methods from appropriate classes to show dialogs:
public sealed class DialogService : IDialogService
{
// ...
public void ShowMessageBox(MessageBoxSettings settings)
{
return MessageBox.Show(/* ... */);
}
public bool? ShowOpenFileDialog(FileDialogSettings settings)
{
var dialog = new OpenFileDialog();
// ...
return dialog.ShowDialog();
}
// ...
}
Again, usually, view models access services in two ways:
Both ways assumes, that view models never access services, using particular implementations. Instead of this, they are asking service locator or DI-container to provide them available implementation of some service contract:
// getting service through service locator
var dialogService = ServiceLocator.GetService<IDialogService>();
or
// inject service dependency with MEF container
[Import]
private IDialogService dialogService;
You should choose the way to access services yourself, but, ultimately, you'll need to read about several existing implementations of service locators or DI-containers.
And finally, what do you need all this stuff for? Why just don't show message boxes and work with database from view models?
The answer is simple.
The first. With services your view models contains only that code, which is responsible to interact with the view. You have well-structured, decoupled code, where one set of classes interacts with views, another set - with WPF presentation subsystem, another - with database or web-services, etc. Since view model doesn't depend on service implementation, you can change implementation code easily (for example, fix a bug) without affecting view model(s).
The second. You can mock your "real" service with test one, and write unit test for the view model.