5

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.

3
  • What exactly will you add to the models you create from autogenerated WCF classes? Will you add some validation logic there for example? Did you think about not using autogenerated proxy at all? Since both WPF and WCF are controlled by you - you can share a library with service interface and classes between client and server.
    – Evk
    Nov 15, 2016 at 6:52
  • So far I don't have anything extra that I want to add to the models, I only wanted to have that layer to abstract WCF away from WPF and to be prepared for the possibility of adding data or logic there. I did at first not use the auto-generated proxy, but the problem is that then I would have to manually create all the async methods. The auto-generated proxy can do that for all the service methods automatically. Nov 15, 2016 at 8:17
  • Small update: There is actually a string property that is missing from one of the WCF entities, which comes from a resource file based on the ID of the entity. This would be one case where a Model would make sense. Nov 15, 2016 at 14:25

1 Answer 1

1

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.

1
  • Thanks Rachel, we've decided to hold back on this until the requirements are clearer. I appreciate the valuable input! Jan 10, 2017 at 13:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.