1

現在取り組んでいる他のプロジェクトで必要とされているため、アセンブリにあるクラスがあります。1つのクラスはそれをクラスファクトリと呼び、クリックイベントハンドラーをアタッチする必要があるコントロールのグループを作成します。特定の機能に基づいてポリモーフィックな動作を決定するアルゴリズムがありますが、それは比較的無関係です。イベントハンドラがアセンブリの一部ではない特定のフォームを開かなければならないため、そのフォームにはこの「ファクトリ」クラスが必要です。循環参照を作成せずに、フォームが定義するハンドラーイベントを本質的に「委任」できる方法はありますか?

簡単な回避策として、2つの別々のクラスを維持する必要がありました。1つはフォームを含むプロジェクトに、もう1つはアセンブリにあります。これは明らかに間違った方法です。

私が何をしようとしているのかはわかっているが、それをどうやってやるのかわからないので、タイトルについては100%確信が持てない。

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Me.Width = 1500
    Dim panel As New Panel
    panel.Location = New Point(0, 0)
    panel.Size = New Size(1000, 200)
    panel.BackColor = Color.Yellow
    Me.Controls.Add(panel)
    Dim factory As New DrawFactory
    factory.DrawPanel(panel, 5)
End Sub

上記は、クラスライブラリにある次のコードとは別のプロジェクトにあります。

Public Class DrawFactory
Private xOffset As Integer = 0
Private Const widthConst As Integer = 50
Public Sub DrawPanel(ByRef panel As Panel, ByVal drawPanels As Integer)
    Application.DoEvents()
    For i As Integer = 0 To drawPanels
        Dim childPanel As New Panel
        childPanel.Location = New Point(xOffset, 0)
        childPanel.Size = New Size(widthConst, panel.Height)
        If i < 1 Then
            childPanel.BackColor = Color.Blue
        Else
            childPanel.BackColor = Color.Pink
        End If
        xOffset = xOffset + widthConst
        ''want to add a handler here to open say form5 which is unknown and undefined in the scope of this class
        panel.Controls.Add(childPanel)
    Next
End Sub
End class

これは私の実際のコードではありませんが、私が直面している問題の要点を表しています。C#またはVB.NETでの回答は問題ありません。

4

2 に答える 2

1

循環参照は、.NETでは技術的に問題ではありません。COMは参照カウントを使用して、オブジェクトを破棄する必要がある時期を判断するため、COMでは問題でした。それぞれが相互に参照している2つのオブジェクトがある場合、循環参照によってどちらのオブジェクトの参照カウントもゼロにならず、したがってオブジェクトが破棄されることはありません(メモリリークが発生します)。ただし、.NETでは、CLRは参照カウントの代わりにガベージコレクションを使用します。ガベージコレクタは、すべてのオブジェクトを定期的に検索して、アプリケーションによって参照されなくなったオブジェクトを見つけます。次に、見つかった場合に死んだオブジェクトをすべて破棄します。ガベージコレクターは、相互にのみ参照され、他には何も参照されていない2つ以上のオブジェクトが両方とも死んでいることを知るのに十分賢いです。したがって、.NETマネージコードでは、

ただし、そうは言っても、イベントハンドラーメソッドをデリゲートとして別のプロジェクトのDrawFactoryクラスに渡すことができます。DrawFactoryクラスは、そのイベントハンドラーを必要なイベントに追加できます。例えば:

Public Sub DrawPanel(ByVal panel As Panel, ByVal drawPanels As Integer, ByVal handler As EventHandler)
    For i As Integer = 0 To drawPanels
        Dim childPanel As New Panel
        '...
        AddHandler panel.Click, handler
        panel.Controls.Add(childPanel)
    Next
End Sub

次に、フォームで、次のようなEventHandler署名に一致するメソッドが必要になります。

Private Sub Panel_Click(ByVal sender As Object, ByVal e As EventArgs)
    Form2.Show()
End Sub

そして、次のようにファクトリを呼び出すことができます。

factory.DrawPanel(panel, 5, New EventHandler(AddressOf Panel_Click))
于 2012-06-19T13:41:25.733 に答える
0

はい、私はあなたがこれを行うことができると信じています。クリックイベントの署名は次のようになります。

private void ButtonOkClicked(object sender, RoutedEventArgs e)
{

}

クラスファクトリのCreateメソッドはアクションを受け取る可能性があるため、次のようになります。

void Create(Action<object, RoutedEventArgs> clickAction)
{
  var btn = new Button();
  btn.OnClick += clickAction;
}

これがお役に立てば幸いです。お役に立てない場合はお知らせください。

于 2012-06-19T13:41:41.210 に答える