3

アプリケーション全体で複数回使用される特定のファイルのメタデータにすばやくアクセスできるように設計されたクラスがあります。残念ながら、一部のメタデータは、非常に長時間実行されるメソッド呼び出しでしか抽出できません。

長時間実行されるメソッドの非同期ラッパーを提供する別のクラスがあります (ファイルのサイズによっては 5 分以上かかる場合があります) が、この非同期メソッドを呼び出す方法と、それが適切かどうかを理解しようとしています。それをコンストラクターに入れるか、このシナリオに適した設計パターンがあるかどうか。

私の質問を試して説明するための疑似コードを次に示します。

public class MetaData
{
    public string Data1 { get; private set; }
    public string Data2 { get; private set; }

    public MetaData(String filepath)
    {
        var extractor = new ExtractMetaData(filepath);  //create instance of class that fetches the metadata

        this.Data1 = extractor.GetData1(); // short running method

        extractor.Data2Received += Data2Received;  
        extractor.GetData2Async();  // long running method, called with via async method

    }        

    private void Data2Received(object sender, MetaDataEventArgs args)
    {
        this.Data2 = args.Data;  // finally set Data2 property
    }
}

class ExtractMetaData
{

    public event Data2ReceivedEventHandler Data2Received;

    public ExtractMetaData (string filePath) { }

    public String GetData1();  // very fast method to get Data1
    public void GetData2Async();  // very slow method to get Data2

}

私が理解しようとしているのは、これを達成するためのより良い方法があるかどうかです。

現在のコードでは、構築されるのを待つ必要はほとんどありませんが、メソッドが返されてイベントが発生する前MetaDataに誰かがMetaData.Data2プロパティにアクセスしようとすると、応答が返されます。ただし、返された後に if を呼び出すと、正しい情報が含まれます。このメソッドが完了したことをユーザーに通知する方法が本当にないため、コンストラクターを待つ必要はなく、すべてのプロパティが完了するまで待たなければならないため、これがユーザーエクスペリエンスの低下につながるのではないかと心配しています。悩ませる。GetData2Async()Data2Receivednull

4

3 に答える 3

2

まず、完了したことをユーザーに通知する方法はないとおっしゃいましたData2。それは真実ではありません。たとえば、イベントやTask.

しかし、実際にはクラスを再構築する必要があると思います。取得にData2は非常に時間がかかるとおっしゃいましたが、これはおそらく多くのリソースを使用することを意味します。そのため、必要がない限り、初期化を試みるべきではないと思いますData2。そして、どうやってそれを知っていますか?ユーザーはあなたに言う必要があります。そして理想的には、ユーザーが を望まない場合は、Data2アクセスすることさえできないようにする必要MetaDataBasicMetaDataありExtendedMetaDataますBasicMetaData

ではExtendedMetaData、初期化が完了したことをユーザーに通知する何らかの方法 (イベントを使用する可能性が最も高い) を用意するか、初期化が完了するまでコンストラクターを待機させることができます (そのためMonitor.Wait()に andMonitor.Pulse()を使用できます)。

個人的には、 を返す静的ファクトリ メソッドがあれば最適なオプションだと思いますTask<ExtendedMetaData>Resultこのようにして、ユーザーは結果を同期的に ( を使用して) または非同期的に ( またはContinueWith()を使用して)待つことがawaitできます。これは、.Net 4.5 で特に役立ちますが (理由によりawait)、.Net 4.0 でも役立ちます。残念ながら、質問のタグは、.Net 3.5 を使用していないことを示していますTask。可能であれば、アップグレードすることをお勧めします。

于 2013-01-26T03:48:56.217 に答える
1

次のパターンに注意を払う必要があると思います: 遅延読み込み (本当に必要な場合にのみ「長い」メソッドを呼び出す) とプロキシ (必要に応じてキャッシング レイヤーを実装し、内部認識を非表示にします。あなたのオブジェクトの底)。全体の機能を確保するために複数のオブジェクトを使用する場合は、Facade も妥当な選択です。

于 2013-01-26T02:08:07.560 に答える
0

この質問に対して、いくつかの異なる回答が得られます。これが私の見解です。

IMO、現在行っていることなど、コンストラクターで操作を呼び出すべきではありません。コンストラクター内のすべてのものは、MetaData最初からそこにあるべきではありません。

オブジェクトのインスタンス化中に例外がスローされる場合がありますが、これは問題ありませんが、オブジェクトは構築されません。ベスト プラクティスの一部。コンストラクターは短時間で実行する必要があり、コンストラクターの後にオブジェクト グラフが作成されるようにする必要があります。

この質問も見てください: コンストラクターにどのくらいのコードを配置する必要がありますか?

または、依存関係を注入し、データを入力するメソッドを作成する必要があります。

問題をもう少し詳しく説明していただけると助かります。

プロセスと設計を単純化する必要があります。

于 2013-01-26T03:49:17.217 に答える