Synchronizing Multiple Views, Editors & Commit/Cancel
We're thinking about an architecture to support multiple views and editors on the same object. A requirement is the possibility to commit or cancel the changes done on a whole object.
Our requirements are - lot's of objects edited at the same time (up to 10.000 in multiselect mode) - multiple views and editors开发者_运维百科 at the same time - changes in on editor on the object should only reflect in the other views after a succesful commit - the objects in an editor should be committable/cancellable as a whole
We've had a look at several concepts, including the dynamic-wrapper approach (http://www.codeproject.com/KB/cs/dynamicobjectproxy.aspx#EditableProxy%28implementingIEditableObject%299), which we've discarded because of - no Intellisense on dynamics - no compile time checks on dynamics - access on the properties when iterating over them (e.g. for property grids) is very expensive
We've implemented a prototype of architectur in the figure
each editor gets its own clone of the original object. it can then work on it, validate it and commit it into the imodelrepository. when doing that, the original object gets updated and a backendchanged event gets sent out for each clone. The viewmodels of the other editors registered for the backendchanged events and now get new clones to reflect the changes
the positive aspects are: - the imodelrepository only outputs clones, a direct editing of the original is prohibited - each editor can work on it's own clone - there is a way to notify the other clones and update there content if one editor commits a change but the negative aspects are: - each editor/Viewer viewmodel has to look for a backendchanged object that gets sent if the original objects gets changed. it then needs to get a new clone and discard the old one - additionally each editor/viewer has to look for a object deleted event, if another editor deleted the object. it then needs to discard its clone - a lot of clones is needed, which slows down the system, especially for a large number on edited objects at the same time
we're thinking about handing the original to viewmodels registered as viewers only, and using the clones for the real editors. That would cut down the number of clones needed. But there is no way to ensure a readonly original for the viewers (dynamic readonly wrapper causes the same problems as the editableproxy mentioned above)
i would be thankful for any input or ideas as how to simplify the approach, or about a different architecture
thx
If multiple editors above same model object can be opened simultaneously,
then waiting for commit to update the others would be counter intuitive(*),
in this case I'd use the same VM for them all and let them edit the object in its intermediate states too and use a global commit that updates the repository from VM's changes.If multiple editors above same model object can NOT be opened simultaneously,
then one VM (per model object) at a time should do.
You could use T4s to generate a readonly VM class for viewers, that is identical to the original VM class, just without property setters.
(*) E.g. use could update a name, other viewers/editors would still show old name, user could edit name to two different values in two different editors without committing.
If one editors changes are committed, changes in other editor may be lost during recloning.
- Another approach is to have one readonly VM for all viewers (can be T4 generated from editor's VM),
allow multiple editors to update same model object, use timestamp based concurrency (optimistic concurrency) in repository, and continue giving a seperate VM to each editor.
Changes will be feed to repository on commits, already open editors will not be aware of changes until they try to commit.
When they try to commit, if model object has been edited, a exception will be thrown (e.g. OptimisticConcurrencyException in EF), which you can catch to enable user to react to (disgard, overwrite, merge).
精彩评论