I attempted just such a mechanism in a prior incarnation of the library (the C++ version I originally started with). It didn't work out so well.
The first thing you need to do is put boundaries on user intent. The program might make several changes in response to a single user action. The user expects all of those changes to get rolled back together.
The next thing is to store prior state and next state. This is simple with atomic value types (like int). But it's more difficult with collections. And it's almost impossible to get reference types correct without having more information. Is it a reference
to something else in the document, or do I own it, for example.
Third, there's a difference between document data and navigation. If the user changes the data model, you want that to undo. But if they just switch to a different point-of-view, you don't. The library would have to be told the difference.
And finally there are all the side-effects. There's no telling what your application might need to do when the user makes a change. Are the side-effects captured in the undo itself, or do they need to be recomputed? It depends.
So instead, I just decided to make Update Controls focus on one thing: dependency discovery. It can do this well, but it will fail if it tries to take on too much.
BTW, Update Controls does not use reflection, other than in the places it integrates with WPF data binding. It doesn't care what your independent field is named, what its data type is, or what value you're storing in it. It only cares about when you set
it and when you get it.