tags:

views:

76

answers:

3

Some background information:

I am working on a C#/WPF application, which basically is about creating, editing, saving and loading some data model.

The data model contains of a hierarchy of various objects. There is a "root" object of class A, which has a list of objects of class B, which each has a list of objects of class C, etc. Around 30 classes involved in total.

Now my problem is that I want to prompt the user with the usual "you have unsaved changes, save?" dialog, if he tries to exit the program. But how do I know if the data in current loaded model is actually changed?

There is of course ways to solve this, like e.g. reloading the model from file and compare against the one in memory value by value or make every UI control set a flag indicating the model has been changed. Now instead, I want to create a hash value based on the model state on load and generate a new value when the user tries to exit, and compare those two.

Now the question:

So inspired of that, I was wondering if there exist some way to generate a hash value from the (value)state of some arbitrary complex object? Preferably in a generic way, e.g. no need to apply attributes to each involved class/field.

One idea could be to use some of .NET's serialization functionality (assuming it will work out-of-the-box in this case) and apply a hash function to the content of the resulting file. However, I guess there exist some more suitable approach.

Thanks in advance.

Edit:

Point taken about the hashing and possible collisions. Instead, I am going for deep comparing value by value. I am already using the XML serializer for persistence, so I am just going to serialize and compare chars. Not pretty, but it does the trick in this case.

A: 

I would advice against this. Different objects can have the same hash. It's not safe to rely on this for checking if changes have to be saved.

compie
Point taken. I think I will revise the problem to a value-based comparison of two objects and no hashing involved.
Jan
+1  A: 

Ok you can use reflection and some sort of recursive function of course. But keep in mind that every object is a model of a particular thing. I mean there maybe a lot of "unimportant" fields and properties.

And, thanks to @compie! You can create a hash function just for your domain. But this requires strong mathematic skills.

And you can try to use classic hash functions like SHA. Just assume that your object is a string or byte array.

Trickster
Getting the values of the object as an array using reflection sounds tempting. More tempting than implementing IComparers for 30 classes.
Jan
A: 

Because this is a WPF app, it may be easier than you think to be notified of changes as they happen. The event architecture of WPF allows you to create event handlers at a level somewhere above where the event actually originates. So, you could create event handlers for the various "change" events of your UI elements in the root window of your interface and set the "changed" flag at that scope.

WPF Routed Events Overview

Daniel Pratt
Thanks for your reply. I do know about Routed Events, but in my case I have several windows for different parts of the model and I use Property Grids from WinForms, so it will not be entirely trivial to implement. However, still a viable solution.
Jan