MVVM で構築された WPF アプリケーションに自己追跡エンティティを渡す WCF クライアントがあります。アプリケーション自体には動的インターフェースがあります。ユーザーは、自分の役割や実行しているタスクに応じて、作業領域に表示するオブジェクトを選択できます。
私の自己追跡エンティティにはかなりの数のナビゲーション プロパティがあり、それらの多くは必要ありません。これらのオブジェクトの一部は非常に大きくなる可能性があるため、これらのプロパティは要求があった場合にのみロードしたいと考えています。
私のアプリケーションは次のようになります。
[WCF] <---> [ClientSide Repository] <---> [ViewModel] <---> [View]
私のモデルは自己追跡エンティティです。クライアント側リポジトリは、要求元の ViewModel にモデルを返す前に、必要に応じて LazyLoad メソッドをフックします。すべての WCF サービス呼び出しは非同期です。つまり、LazyLoad メソッドも非同期です。
LazyLoad の実際の実装で問題が発生しています。ここに私が思いついたオプションがあります。
編集 - コードサンプルを削除して、これを読みやすく理解しやすくしました。見たい場合は、以前のバージョンの質問を参照してください
オプション A
Getter で WCF サーバーからモデルのプロパティを非同期的に LazyLoad する
良い:オンデマンドでのデータの読み込みは非常に簡単です。XAML のバインドによってデータが読み込まれるため、コントロールが画面上にある場合、データは非同期に読み込まれ、そこにあるときに UI に通知されます。そうでない場合、何もロードされません。たとえば<ItemsControl ItemsSource="{Binding CurrentConsumer.ConsumerDocuments}" />
、データをロードしますが、インターフェイスのドキュメント セクションが存在しない場合は何もロードされません。
悪い例:空のリストを返すため、このプロパティを開始する前に他のコードで使用することはできません。たとえば、ドキュメントが読み込まれていない場合、次の呼び出しは常に false を返します。
public bool HasDocuments
{
get { return ConsumerDocuments.Count > 0; }
}
オプション B
必要に応じて手動で呼び出してデータをロードする
良い:実装が簡単 -メソッドLoadConsumerDocumentsSync()
とLoadConsumerDocumentsAsync()
メソッドを追加するだけ
悪い例: Bindings で使用する場合を含め、データにアクセスする前にデータをロードすることを忘れないでください。これは簡単に思えるかもしれませんが、すぐに手に負えなくなる可能性があります。たとえば、各 ConsumerDocument には UserCreated と UserLastModified があります。拡張機能、電子メール、チーム、ロールなどの追加のユーザー データを表示する ToolTip を使用して UserModel を定義する DataTemplate があります。そのため、ドキュメントを表示する ViewModel では、 を呼び出してからLoadDocuments
、それらをループして and を呼び出す必要がLoadConsumerModified
ありLoadConsumerCreated
ます。それも続くかもしれません...その後、私はしなければなりませLoadUserGroups
んLoadUserSupervisor
. また、 a のようなものがプロパティをUser
持ち、 aがプロパティを持つ循環ループのリスクを冒します。Groups[]
Group
Users[]
オプション C
これまでのところ私のお気に入りのオプションは... プロパティにアクセスする 2 つの方法を作成することです。1 つの同期と 1 つの非同期。バインドは Async プロパティに対して行われ、すべてのコードで Sync プロパティが使用されます。
良い:データは必要に応じて非同期に読み込まれます - まさに私が望むものです。これらの追加のプロパティ/メソッドを生成するために T4 テンプレートを変更するだけでよいため、追加のコーディングはそれほど多くありません。
悪い例:同じデータにアクセスする方法が 2 つあると、効率が悪く、混乱を招きます。Consumer.ConsumerDocumentsAsync
の代わりにいつ使用する必要があるかを覚えておく必要がありますConsumer.ConsumerDocumentsSync
。WCF サービス呼び出しが複数回実行される可能性もあります。これには、IsConsumerDocumentsLoaded などのすべてのナビゲーション プロパティに追加の IsLoaded プロパティが必要です。
オプション D
非同期ロードをスキップし、セッターですべてを同期的にロードします。
良い:非常にシンプルで、余分な作業は必要ありません
悪い:データの読み込み時に UI がロックされます。これはいらない。
オプション E
SOの誰かに、これを行う別の方法があることを教えてもらい、コードサンプルを教えてもらいます:)
その他の注意事項
一部の NavigationProperties は、オブジェクトをクライアントに返す前に WCF サーバーに読み込まれますが、それ以外はコストが高すぎてそれを行うことができません。
オプション C の Load イベントを手動で呼び出すことを除いて、これらはすべて T4 テンプレートを介して実行できるため、私が行うコーディングはほとんどありません。私がしなければならないことは、クライアント側のリポジトリで LazyLoad イベントをフックし、それを適切なサービス呼び出しに向けることだけです。