📜 ⬆️ ⬇️

Photographing objects in C #: Chronicle and comparison of images, reconstruction of the state of the image

When developing applications, the following scenario is often encountered: there is some set of data available for viewing and editing, for example, these can be business entities or application settings. At the moment when the user decides to edit something, a special form with the necessary I / O fields and other controls usually becomes available to him. If he makes any adjustments to the data, then when processing the form, it is good practice to request confirmation before final application of the changes made. If the user consents, the data is updated in the source and on the interface, and the cancellation uses the old values.

This task includes two subtasks:

1) when the user leaves the editing form, it is necessary to understand whether he really made the changes in order not to ask a confirmation question for nothing and not to overwrite identical data;
')
2) if the original entity is subjected to editing, and not its copy, then in the case of cancellation, it is necessary to preserve the possibility of rolling back to the original values.

In this article, we will look at the generalized and very laconic [several lines of code!] Approach to solving such problems, based on the use of the Replication Framework library.

image


Consider an example application . Let the list of entities be given, among which the user can select any and click on the edit button [in the original or copy mode].



In the mode of editing the original, when the entity changes in the dialog box, the corresponding values ​​are immediately updated in the main one, which is not happening in the copy mode.



After confirming the changes, a list of all the differences found is displayed, if the Show detailed changes flag is raised, or a message is displayed that detects at least one difference [in real situations, sometimes this behavior is enough].



Undo uses old values.



Now take a look at the code of the method that is responsible for this behavior.

private void Edit<T>(T sourceEntry, bool useCopy, bool showChanges, ReplicationProfile replicationProfile) { var cache = new ReconstructionCache(); var sourceSnapshot = sourceEntry.CreateSnapshot(cache, replicationProfile); var editableEntry = useCopy ? sourceSnapshot.ReplicateGraph() : sourceEntry; if (GetView(editableEntry).ShowDialog() == true) { var resultSnapshot = editableEntry.CreateSnapshot(null, replicationProfile); var changes = sourceSnapshot.Juxtapose(resultSnapshot) .Where(j => j.State != Etalon.State.Identical); if (changes.Any()) { MessageBox.Show(showChanges ? changes.Aggregate("", (x, y) => x + y + Environment.NewLine) : "Any changes has been detected!"); UpdateSourceData(editableEntry); UpdateUserInterface(); } else MessageBox.Show("There are no any changes."); } else if (!useCopy) sourceSnapshot.ReconstructGraph(cache); } 

Entity entity
  public class Person : INotifyPropertyChanged { private int _id; private string _name; private string _birthday; private string _phone; private string _mail; public event PropertyChangedEventHandler PropertyChanged = (o, e) => { }; private void Set<T>(ref T target, T value, [CallerMemberName]string caller = "") { if (Equals(target, value)) return; target = value; PropertyChanged(this, new PropertyChangedEventArgs(caller)); } public int Id { get => _id; set => Set(ref _id, value); } public string Name { get => _name; set => Set(ref _name, value); } public string Birthday { get => _birthday; set => Set(ref _birthday, value); } public string Phone { get => _phone; set => Set(ref _phone, value); } public string Mail { get => _mail; set => Set(ref _mail, value); } } 


Replication profile for the Person entity
  private static readonly ReplicationProfile PersonRepicationProfile = new ReplicationProfile { MemberProviders = new List<MemberProvider> { new CoreMemberProviderForKeyValuePair(), new CoreMemberProvider(BindingFlags.Public | BindingFlags.Instance, Member.CanReadWrite), } }; 


As you can see, the method is quite generalized and can be used for entities of other types.

Now pay attention to the key points. The work of the Replication Framework library is based on the use of snapshots of objects at arbitrary points in time, that is, using the Snapshot extension method, you can easily chronicle the mutations [change history] of an arbitrary object or graph.

  var cache = new ReconstructionCache(); var sourceSnapshot = sourceEntry.CreateSnapshot(cache, replicationProfile); ... var resultSnapshot = editableEntry.CreateSnapshot(null, replicationProfile); 

You can then compare two snapshots to identify differences in the state of the graph between any two control points.

  var changes = sourceSnapshot.Juxtapose(resultSnapshot) .Where(j => j.State != Etalon.State.Identical); 

By calling the ReplicateGraph method, you can recreate a new copy of the graph that is identical to the one recorded in the snapshot, and with the help of ReconstructGraph, if you have a replication cache, you can reconstruct the graph, that is, return the old instance to its previous state.

  var editableEntry = useCopy ? sourceSnapshot.ReplicateGraph() : sourceEntry; 

  var cache = new ReconstructionCache(); var sourceSnapshot = sourceEntry.CreateSnapshot(cache, replicationProfile); ... else if (!useCopy) sourceSnapshot.ReconstructGraph(cache); 

More information about using the library can be found in previous publications:

1) Replication Framework • deep copying and generalized comparison of connected object graphs
2) Generalized copying of connected graphs of objects in C # and nuances of their serialization

The library is free for non-commercial and educational projects, and on Nuget a trial version is available, which is functional until the end of summer. To obtain a licensed version with an unlimited period of validity and access to the source code, you must send a request to makeman@tut.by .

The external simplicity of use and good library functionality make for a great and painstaking work on its creation and debugging, therefore any material support and the purchase of a commercial license are very welcome!

Inspiration to you, reader!

Source: https://habr.com/ru/post/333846/


All Articles