C#でオブジェクトを撮影します。画像の記録と比較、画像の状態の再構築

アプリケーションを開発する場合、次のシナリオがよく発生します。たとえば、ビジネスエンティティまたはアプリケーション設定など、表示および編集に使用できる特定のデータセットがあります。 ユーザーが何かを編集することを決定した時点で、必要な入出力フィールドと他のコントロールを備えた特別なフォームが通常利用可能になります。 彼がデータを修正した場合、フォームを処理するときに、最終的な変更の適用前に確認要求が良いトーンになります。 ユーザーが同意すると、ソースとインターフェイスでデータが更新され、キャンセルすると古い値が使用されます。

このタスクには2つのサブタスクが含まれます。

1)ユーザーが編集フォームを離れるとき、確認の質問を無駄にせず、同一のデータを上書きしないように、実際に変更を加えたかどうかを理解する必要があります。

2)ソースエンティティがそのコピーではなく直接編集される場合、キャンセルの場合、元の値にロールバックする機能を保持する必要があります。

この記事では、 レプリケーションフレームワークライブラリの使用に基づいて、このような問題を解決するための一般化された非常に簡潔な[数行のコードサイズ!]アプローチを検討します。

画像


サンプルアプリケーションを考えてください。 エンティティのリストを指定します。その中からユーザーが任意のエンティティを選択し、[オリジナルモードまたはコピーモードで]編集ボタンを押します。



オリジナルの編集モードでは、ダイアログボックスでエンティティが変更されると、対応する値がメインの値ですぐに更新されますが、これはコピーモードでは発生しません。



変更を確認した後、[ 詳細な変更を表示]フラグが立てられている場合、見つかったすべての相違のリストが表示されるか、少なくとも1つの相違が検出されたというメッセージが表示されます。



キャンセルする場合、古い値が使用されます。



次に、この動作を担当するメソッドのコードを見てみましょう。

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); } 

個人エンティティ
  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); } } 


個人エンティティのレプリケーションプロファイル
  private static readonly ReplicationProfile PersonRepicationProfile = new ReplicationProfile { MemberProviders = new List<MemberProvider> { new CoreMemberProviderForKeyValuePair(), new CoreMemberProvider(BindingFlags.Public | BindingFlags.Instance, Member.CanReadWrite), } }; 


ご覧のとおり、このメソッドは非常に一般化されており、他のタイプのエンティティに使用できます。

ここで重要な点に注意を払いましょう。 レプリケーションフレームワークライブラリの操作は、任意の時点でのオブジェクトのスナップショットの使用に基づいています。つまり、スナップショット拡張メソッドを使用すると、任意のオブジェクトまたはグラフの変更履歴[変更履歴]を簡単に作成できます。

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

次に、2つの画像を比較して、2つのコントロールポイント間のグラフの状態の違いを明らかにできます。

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

ReplicateGraphメソッドを呼び出すことで、図で修正されたものと同一のグラフの新しいコピーを再作成し、ReconstructGraphを使用して、レプリケーションキャッシュがある場合はグラフを再構築します。つまり、古いインスタンスを以前の状態に戻します。

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

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

ライブラリの使用に関する詳細については、以前の出版物をご覧ください。

1) レプリケーションフレームワーク•オブジェクトの接続されたグラフのディープコピーと一般化された比較
2) C#のオブジェクトの接続されたグラフの一般化されたコピーとそれらのシリアル化のニュアンス

このライブラリは、非営利および教育プロジェクト向けに無料で提供されています。また、Nugetには試用版が用意されており、夏の終わりまで機能しています。 有効期限が無制限でソースコードにアクセスできるライセンスバージョンを取得するには、 makeman@tut.byにリクエストを送信する必要があります。

外部からの使いやすさとライブラリの優れた機能の背後には、作成とデバッグに関する多くの骨の折れる作業があります。そのため、商用ライセンスの実質的なサポートと購入は大歓迎です!

読者にインスピレーションを!

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


All Articles