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 使用引用计数来确定何时需要销毁对象。如果您有两个相互引用的对象,则循环引用将导致两个对象的引用计数均不为零,因此它们永远不会被销毁(导致内存泄漏)。然而,在 .NET 中,CLR 使用垃圾收集而不是引用计数。垃圾收集器会定期搜索所有对象以查找应用程序不再引用的任何对象。然后它会销毁所有如果找到的死对象。垃圾收集器足够聪明,可以知道两个或多个仅被彼此引用而没有其他对象的对象都是死的。因此,在 .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 回答