MVVM Best Practices – WPF Client and WCF Duplex Service

designdesign-patternsmvvmwcfwpf

I've been thinking about how to design my WPF application, which receives data from a WCF duplex service, but I'm afraid of over engineering.

I thought about abstracting away the WCF communication completely from the WPF client by creating a "proxy client" library that implements the service and callback interfaces internally.

This way I don't have to create the callback class in the WPF application, but subscribe to events in the proxy client that are invoked when the callback methods in it are called by the service. This would allow me to also hide the service reference from WPF.

Then in WPF, all I will do is:

var client = new ApiClient(); //This is the client library
var stuff = client.GetStuff(); //Some service method
client.StuffDeleted += OnStuffDeleted; //Event that is invoked by library on callback

I would probably instantiate the client only once as a Singleton object for all ViewModels to call.

Then I thought I could take this further by creating "Model" classes that are almost identical to the WCF service reference generated classes (data contracts), adding another layer on top of the proxy client, and using automapper to create my models, then returning those to WPF instead of data contract classes.

I figured this way I would achieve complete separation from my WCF service, and having an extra layer would allow me to add metadata to my models before returning them, and then in the WPF side I will use these Models to construct the ViewModel which is meant for viewing/binding only.

Having such a client would also make it easier to centralize business logic, error handling, and make it simpler to do unit testing since the WCF client is a single independent component.

The problem is that I'm afraid of over engineering this. The database has EF entities, the WCF service has its own DTO classes, then I would have Models, and then ViewModels. I've also noticed that the generated classes from WCF implement the INotifyPropertyChanged interface, which makes me think they were intended to be used as models (or to send an updates to the service?).

I'll try to summarize my main questions in bullet points:

  • In M-V-VM, is it good practice to use the service reference genereated classes as Models?
  • Is there much benefit in completely abstracting away WCF from WPF with a proxy client?
    • Callback methods would invoke events that WPF is subscribed to
  • Why do the generated service reference classes implement INotifyPropertyChanged?

Is this design overkill?

Thank you very much.

UPDATE:

Visualisation of what I'm trying to do:

enter image description here

As can be seen, the Proxy client in the middle has 2 layers (classes):

The first class is what WPF instantiates as a Singleton and uses to get back model classes.

The second class is a wrapper around the Service Reference client, and is called by the first layer. This is purely for data access purposes.

I have not added the callback methods which will be events that WPF subscribes to.

Best Answer

I had a situation like this in the past, and we ended up creating a separate WPF Model layer for the application.

I'm not sure how much has changed since then, however our reasons for it were :

  • We wanted read-only properties in the application, and the DTOs generated by the DataContracts had to be read/write

  • Some classes were very large, but the UI model only needed a much smaller section of the data.

  • Some properties on the UI layer had custom logic. For example, we wanted to keep the db property as an int of 123, however for UI purposes we wanted a string of "000123"

  • We wanted to keep the possibility open in the future that we might change the technology stack of a layer, such as replace WCF or EF layer with some other alternate. By separating them out, we would only have to rewrite one layer instead of everything in the application.

  • We wanted to add an Encryption layer to some data, so data would be encrypted at rest or for transfer... I don't recall much about this requirement, but it did factor into our decision.

Our end result was :

  • Project for WPF Models that only creates the UI Models used by the application, using the correct properties, data types, and scope that the UI requires.

  • Project for Data Access Layer, which would take care of converting WPF models to DTO or EF models for transfer to database layer. We actually used AutoMapper for this too.

  • The actual WCF project, with auto-generated classes from WCF

  • The actual EF project, with auto-generated EF models and procedures

If I remember correctly, from the WPF application layer, we would do something like :

ISomeService service = DAL.SomeService();
ISomeModel stuff = service.GetStuff();

The DAL would return a service class that met some interface. If we ever wanted to replace the service layer with something else, we could without impacting the rest of the WPF application.

In addition, ISomeModel could implement items specific to the WPF application itself, such as custom logic or events. It didn't have to be tied to the data object we send/receive to the database.