2009-05-13 15 views
2

私はValidateItemイベントを追加するカスタムコレクションを持っています。このValidateItemイベントは、アイテムがカスタムコレクションに追加または更新されるたびに呼び出されます。C#Custom EventArgs質問

派生クラスがイベントを購読し、アイテムが「有効」であるかどうかの独自のロジックを判断し、アイテムが「無効」であればコレクションに追加することを禁止します。

しかし、私はイベントに発信者に何が起こっているのか、また何が起こっているのかについての情報を伝える方法を理解しようとしています。

私のカスタムeventargsはCancelEventArgsを継承しているので、Cancelビットを呼び出し元に渡すことができます。しかし、エラー情報(エラーコード、メッセージなど)がこのように戻されるケースは一度もなかったので、これが最善の方法ではないかと思います。

カスタム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; } 
} 

UPDATE:

はここに私のEventArgsクラスで私は別の他のオプションは、このようなものを使用することですとします派生クラスで

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

方法。私はパラメータを避ける方が好きですが...

誰もが各アプローチの長所と短所について考えていますが、私はそれらを聞いてみたいです!

おかげで、 マックス

答えて

3

イベントを使用することは、おそらく最適な設計アプローチではありません。それは、この動作をオーバーライドすることでしょう継承クラスがあるので

、この方法は、保護されたとしてマークされ、仮想する必要があります。

protected virtual bool Validate(object item); 

は、私もそうにあなたの最初の本能を、以下、パラメータに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)。

+0

よく言われて+1 –

0

さて、あなたはカスタム検証イベント引数と一緒に、独自のカスタム検証イベントを、作成した場合、私はあなたが、例外の場合を投げるのではなく、ステータス/エラーコードを戻すのを好むだろうと想定何か検証しません。

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

マルク・

0

:-)迅速な思考のカップルをあなたのニーズに合わせて:

私がいるEventArgsクラスの「通常」のパターンに合致するように読み取り専用のプロパティになるだろう。

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

質問:EventArgsプロパティはどのように使用しますか?

+0

この場合、読み取り専用は機能しません。 CancelEventArgsを見ると、bool Cancelは読み取り専用ではなく、呼び出し元に情報を渡すために使用されます。このアプローチについて、私は「面白い」と私を襲ってしまいます。私は本当にそれに指をかけられません。 イベントargsを使用して、オブジェクト(アイテム)をvalidateメソッドに渡します。validateメソッドは、必要なものを実行します。最も単純な例では、アイテムがコレクションに存在しないことを確認し、 Cancel boolと潜在的にすべてのエラーメッセージを返します。 –

+0

もちろん。私は間違った方向に考えていた...もう一つのことが私の心を打った;検証イベントに2つの異なるリスナーが存在し、いずれかがCancel = trueを設定し、もう1つがCancel = falseを設定する場合はどうなりますか?私はあなたと同じ感情を得る。ここには何か悪いことがあります; o) –

0

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

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

0

EventArgsとCancelEventArgsには、情報をサブスクライバに伝達するメンバーがありません。 通常、これらのクラスのいずれかから継承し、情報を運ぶために1人以上のメンバーを追加します。 クラスを汎用クラスにすることもできます。そのため、送信するデータが異なるたびに新しいEventArgsクラスを作成する必要はありません。

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

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

1

あなたが実際に説明しているものは、実際にはイベントで見られる観察者の観察可能なパターンには合っていないと思います。

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

+0

私はこのアプローチについて私に迷惑をかけるものの一部だと思います。しかし、その後、変更可能なCancelプロパティを持つCancelEventArgsがすでにパターンに違反していませんか?だから、仮に、余分なデータを追加するのは間違っていますか? –

+0

キャンセルイベントargは、イベントがキャンセルされた行を他のイベントに通知します。それは、他の観察者が何かをしないことを知る方法です。イベントの問題の1つは、すべてのサブスクライバが非決定論的な順序で呼び出されることです。これは、ここで何をしたいのか正確には分かりません。 –