2009-03-20 2 views
3

他の開発者に使用するクラスライブラリを開発しており、WithEvents(または他の言語でも同様)を使用して自分のクラスのインスタンスを宣言したり、クラス内で定義されたデリゲート。私はちょうどこれのようにそれをすることによってここで冗長であるか?デリゲートを使用してイベントを宣言する

Public Delegate Sub TimerElapsedDelegate(ByVal sender As Object, ByVal e As System.EventArgs) 
Public Event TimerElapsed(ByVal sender As Object, ByVal e As System.EventArgs) 
Private _TimerElapsed As TimerElapsedDelegate = Nothing 

イベントを宣言して、それらにAddHandlerなどを実行させるだけでいいですか?

このアドバイスをいただきありがとうございます...私は重複していると思うし、DRYの原則を避けることは言うまでもなく、無意味なコードを望んでいないと思います。

{編集}だけコードの残りの部分は、このクラスのインスタンスが実行する「作業」が別のスレッドで行われること応力を投稿したかった。{/編集}

#Region "Delegates" 
Public Delegate Sub TimerElapsedDelegate(ByVal sender As Object, ByVal e As System.EventArgs) 
Public Event TimerElapsed(ByVal sender As Object, ByVal e As System.EventArgs) 
Private _TimerElapsed As TimerElapsedDelegate = Nothing 
Public Property OnTimerElapsed() As TimerElapsedDelegate 
    Get 
     Return _TimerElapsed 
    End Get 
    Set(ByVal value As TimerElapsedDelegate) 
     If value Is Nothing Then 
      _TimerElapsed = Nothing 
     Else 
      If _TimerElapsed Is Nothing Then 
       _TimerElapsed = value 
      Else 
       _TimerElapsed = System.Delegate.Combine(_TimerElapsed, value) 
      End If 
     End If 
    End Set 
End Property 
Private Sub TriggerTimerElapsed() 
    If OnTimerElapsed IsNot Nothing Then 
     OnTimerElapsed.Invoke(Me, New System.EventArgs) 
    End If 
    RaiseEvent TimerElapsed(Me, New System.EventArgs) 
End Sub 

Public Delegate Sub ItemReadyForQueueDelegate(ByVal sender As Object, ByVal e As System.EventArgs) 
Public Event ItemReadyForQueue(ByVal sender As Object, ByVal e As System.EventArgs) 
Private _ItemReadyForQueue As ItemReadyForQueueDelegate = Nothing 
Public Property OnItemReadyForQueue() As ItemReadyForQueueDelegate 
    Get 
     Return _ItemReadyForQueue 
    End Get 
    Set(ByVal value As ItemReadyForQueueDelegate) 
     If value Is Nothing Then 
      _ItemReadyForQueue = Nothing 
     Else 
      If _ItemReadyForQueue Is Nothing Then 
       _ItemReadyForQueue = value 
      Else 
       _ItemReadyForQueue = System.Delegate.Combine(_ItemReadyForQueue, value) 
      End If 
     End If 
    End Set 
End Property 
Private Sub TriggerItemReadyForQueue(ByVal oItem As h3Budgeteer.FileSystem.ReportTemplateFile.ReportTemplate) 
    If OnItemReadyForQueue IsNot Nothing Then 
     OnItemReadyForQueue.Invoke(Me, New ItemReadyForQueueEventArgs(oItem)) 
    End If 
    RaiseEvent ItemReadyForQueue(Me, New ItemReadyForQueueEventArgs(oItem)) 
End Sub 
Public Class ItemReadyForQueueEventArgs 
    Inherits System.EventArgs 
    Private _ReportTemplate As h3Budgeteer.FileSystem.ReportTemplateFile.ReportTemplate = Nothing 
    Public ReadOnly Property ReportTemplate() As h3Budgeteer.FileSystem.ReportTemplateFile.ReportTemplate 
     Get 
      Return _ReportTemplate 
     End Get 
    End Property 
    Public Sub New(ByVal oReportTemplate As h3Budgeteer.FileSystem.ReportTemplateFile.ReportTemplate) 
     _ReportTemplate = oReportTemplate 
    End Sub 
End Class 

終了リージョン

+0

この場合の「代理人」は基本的に自家製のイベントです。私はそれを削除するだろう。 –

答えて

4

私は完全に委任を完全に削除すると言います。

あなたの代議員は、イベントとまったく同じことを行っています。あなたは、フレームワークのEvent呼び出しを使用する代わりに、あなた自身のイベント配管を書いています。イベントは、あなたが書いたものとほぼ同じですが、使用が簡単であることを除けば、イベントからの退会を容易にします。

両方を提供する利点はありません - イベントはあなたの「委任」が行うすべてのことを行い、はるかに明確です。

(以前:)

あなたはクラスライブラリとしてこれを開発している場合、私はちょうどあなたのクラスがシールされていない作り、そしてより多くの標準的なアプローチを次のようお勧めします。ロジックをオーバーライドしたり、コードに挿入してイベントを許可する通常の方法は、サブクラス化のフックを提供することです。

このような状況では、ユーザーは自分のロジックをプラグインできるようにすることができます。しかし、多くの場合、保護された仮想関数を使用すると、これがより明確になり、達成がはるかに容易になります。

イベントは正確には、ユーザーに何らかの「イベント」を通知するイベントです。これらはユーザーがデリゲートを添付するフックでなければなりません。

たとえば、デリゲートとイベントを提供する代わりに、基本的なWindows Formsコントロールは保護されたメソッド(OnMouseDownなど)と、デフォルトで起動されるイベント(MouseDown)を使用します。

これにより、ユーザーはクラスをサブクラス化し、ロジックをオーバーライドすることができます(これにより、デリゲートが必要な理由が考えられます)。

私が代議員を提供する1つの場所は、まれにあなたのクラスまたはメソッドがロジックをユーザーによって追加する必要がある場所です。この場合、抽象基本クラスを提供するか、そのロジック用に渡される代理人を持つことができます。これの良い例は、LINQの.Where()メソッドです。フィルタリングに使用される述語なしでは無駄なので、この場合、デリゲートを渡すことは意味があります。ただし、これに関連するイベントはないことに注意してください。実際には別の機能を提供することがあります。

+0

私はおそらくこのクラスは別のスレッドで "仕事"を実行することを追加する必要があります、それは何か違いがあります、あなたはどう思いますか? – hmcclungiii

+0

いいえ - 違いはありません。実際、サブクラス化を使うことが重要になると思います。デリゲートを渡すことを許可すると、誤ってスレッド間の同期問題が発生する可能性が高くなります。 –

+0

匿名メソッドとして別のスレッドからデリゲートを渡すと、他のスレッドからステートを渡すのが簡単になります。この場合、スレッド間の問題が発生する可能性があることをユーザーが認識していない可能性があります。サブクラス化はより明確であり、この場合は文書化が容易です。 –

0

あなたのクラスライブラリに必要なのは、公開イベントコード行を書くことだけです。

Public Event TimerElapsed(ByVal sender As Object, ByVal e As System.EventArgs) 

もちろん、あなたのライブラリのどこにでもイベントを発生させてください。どのクライアント開発者もイベントにハンドラを追加することになります。

あなたのライブラリがそのクラスからのイベントを処理しない限り、その冗長性は不要です。

+0

公開イベントの宣言だけで、私の考えている問題は、オブジェクトからのイベントを処理するすべてのオブジェクトが、自分のオブジェクトへの参照を必要とするということです。どうしてそんなに緊密に結合すべきなのかわからないのですか? – hmcclungiii

+0

デリゲートでそれを「扱う」オブジェクトは同じ問題を抱えます。イベントはデリゲートコール以外の何ものでもありません。違いは、イベントに応答して代理人を呼び出すことです。イベントに応答する機能を追加しようとしている場合は、イベントを使用します。これがその目的です。 –

0

generic EventHandlerを使用すると、デリゲートを取り除くことができます。 EventArgsを継承する独自のクラスを作成するだけです。

Public Class Foo 
    Inherits EventArgs 
End Class 

Public Class Bar 
    Public Event MyEvent As EventHandler(Of Foo) 
End Class 

私はあなたが冗長であるとは思わない。 this質問への最初の回答を参照してください。空のイベントハンドラーを追加することで、イベントを聴いたり、処理したりしたくない場合には、イベントを使用している人がNullReferenceExceptionを受け取ることはありません。

-EDIT-

あなたのコードを見た後、私はReedに同意します。共有ライブラリーになる予定だから、はコンシューマーのイベントハンドラーを実行する必要があるとは思わない。あなたの図書館の仕事は、ちょうどそのイベントを断ち切って、消費者に起こったことを知らせることです。イベントを処理するかどうかは、自分の責任です。

あなたのプロパティは冗長であると言います。イベントハンドラは本質的にイベントハンドラです。

+0

しかし、System.EventArgsを継承した同様のデリゲートがこのアプローチを使用していますが、イベントとデリゲートの両方がパラメータとしてこの問題を解決する必要があるため、実際に問題は解決されません。しかし、ありがとう! – hmcclungiii

関連する問題