2

ValidateItem イベントを追加するカスタム コレクションがあります。この ValidateItem イベントは、アイテムがカスタム コレクションに追加または更新されるたびに呼び出されます。

派生クラスがイベントをサブスクライブし、アイテムが「有効」であるかどうかについて独自のロジックを決定できるようにし、「無効」である場合はコレクションへの追加を潜在的に禁止できるようにしたいと考えています。

しかし、イベントの呼び出し元に何が起こっているかを知らせる方法と、何が起こっているかについての情報を返す方法を理解しようとしています。

私のカスタム eventargs は CancelEventArgs を継承しているので、それを使用して Cancel ビットを呼び出し元に戻すことができます。しかし、エラー情報 (エラー コード、メッセージなど) がこの方法で返されるケースを見たことがないので、これが最善の方法ではないのではないかと考えています。

カスタム eventargs クラスに戻したいエラー データを追加する必要がありますか? これには正当な理由がありますか? または、これを達成するための他のより良い方法はありますか?

これが私のeventargsクラスです:

public delegate void ItemValidationEventHandler(object sender, ItemValidationEventArgs e);

public class ItemValidationEventArgs : CancelEventArgs
{
    public ItemValidationEventArgs(object item, ObjectAction state, EventArgs e)
    {
        Item = item;
        State = state;
        EventArgs = e;
    }

    public ItemValidationEventArgs(object item, ObjectAction state) : this(item, state, new EventArgs())
    {
    }

    public ItemValidationEventArgs() : this(null, ObjectAction.None, new EventArgs())
    {
    }

    // is there a better way to pass this info?
    public string ErrorMessage {get; set;}
    public int ErrorNumber {get;set;}

    public object Item { get; private set; }
    public ObjectAction State { get; private set; }

    public EventArgs EventArgs { get; private set; }
}

更新:別のオプションは、次のようなものを使用することだと思います:

virtual bool Validate(object item, ObjectAction action, out string errorMessage) 

派生クラスのメソッド。パラメータを避けることを好む傾向がありますが...

誰かがそれぞれのアプローチの長所と短所について何かアイデアを持っているなら、ぜひ聞いてみたいです!

ありがとう、マックス

4

6 に答える 6

3

これにイベントを使用することは、おそらく最良の設計アプローチではありません。

この動作をオーバーライドするのは継承クラスであるため、メソッドは保護された仮想としてマークする必要があります。

protected virtual bool Validate(object item);

私も on パラメーターを使用するのは好きではないoutので、 を使用する最初の本能に従って、EventArgs検証の結果をカプセル化するクラスを作成する必要があります。

例:

class ValidationResult
{
     public string ResultMessage{get;set;}
     public bool IsValid {get;set;}
}

あなたの方法は次のようになります。

protected virtual ValidationResult Validate(object item)
{
   ValidationResult result = new ValidationResult();

   // validate and set results values accordingly

   return result;
}

イベントに対してこれを使用することの長所と短所は、アクションまたは情報を複数のサブスクライバーに公開する場合にイベントが使用されることを意図していることです。サブスクライバーは、あなたが何も知らないクラスです。彼らが誰であるか、何をしているかは気にしません。また、通知クラスに情報を実際に戻すべきではありません。与えられたイベント情報を処理するだけです。

インスタンスでは、継承されたクラスが唯一のサブスクライバーです。その上で、有用な情報を親クラスに戻せるようにしたいと考えています。継承は、この望ましい動作にはるかに適合し、さまざまなタイプの検証クラスを簡単に実装することもできます。イベントを使用すると、コードを何度も入力してイベント ハンドラーをアタッチする必要があります (非常に見苦しい IMO)。

于 2009-05-13T21:58:28.607 に答える
1

あなたが説明していることは、あなたが通常イベントで見るであろう観察者、観察可能なパターンに本当に合っているとは思いません。

これらは派生クラスであるため、オブジェクトの検証メソッドを仮想化し、子に特定の検証ルーチンを提供させることを検討します。

于 2009-05-13T19:41:12.183 に答える
0

EventArgs と CancelEventArgs には、サブスクライバーに情報を運ぶメンバーがありません。したがって、通常はこれらのクラスの 1 つから継承し、1 つ以上のメンバーを追加して情報を保持します。クラスをジェネリックにすることもできます。これにより、送信するデータが異なるたびに新しい EventArgs クラスを作成する必要がなくなります。

最後に、独自の ItemValidationEventHandler デリゲート型を作成する代わりに、 を使用できますEventHandler<T>。ここで、T は EventArgs パラメーターの型です。

また、EventArgs = e メンバーは必要ありません。

于 2009-05-13T19:40:19.377 に答える
0

カスタム検証イベント引数と共に独自のカスタム検証イベントを作成する場合、何かが検証されない場合に例外をスローするのではなく、ステータス/エラー コードを返すことを好むと思います。

この場合、例外をスローしない検証が必要な場合は、必要なフィールドをカスタム イベント引数に追加します。これらのフィールドは既にカスタムになっているため、拡張しない理由はありません。ニーズ:-)

マルク

于 2009-05-13T19:29:34.167 に答える
0

いくつかの簡単な考え:

eventargs クラスの「通常の」パターンに準拠するために、プロパティを読み取り専用にします。

おそらく、エラー情報に関連するプロパティは、何らかの ErrorInformation クラスにまとめてラップする必要があります (これにより、その情報を他のメソッドに渡すのが少し簡単になります)。

質問: EventArgs プロパティは何に使用しますか?

于 2009-05-13T19:30:46.507 に答える
0

カスタム イベント引数は、特にイベント ハンドラーとの間で情報をやり取りするために使用されるため、それらを配置するのに適した場所です。

もう 1 つのオプションは、例外をスローすることです。これはかなり手間がかかりますが、イベントに対して実行される他のイベント ハンドラーを停止する必要があります。

于 2009-05-13T19:33:14.897 に答える