由于我正在处理的其他项目需要,我有一个在程序集中的类。 一个类可以称之为Class Factory,创建一组控件,需要附加点击事件处理程序,我有一些算法可以根据某些特征确定多态行为,但相对无关紧要。 由于事件处理程序必须打开不属于我的程序集的特定表单,并且该表单需要此“Factory”类。如果没有创建循环引用,有什么方法可以基本上“委托”表单的处理程序事件来定义?
作为一个简单的工作,我必须维护两个单独的类,一个在项目中,一个在表单中,另一个在程序集中。这显然是错误的方式。
对于标题不是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中给出答案。
答案 0 :(得分: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))
答案 1 :(得分:0)
是的,我相信你可以做到这一点。点击事件签名如下所示:
private void ButtonOkClicked(object sender, RoutedEventArgs e)
{
}
您的类工厂Create方法可以接受Action,所以:
void Create(Action<object, RoutedEventArgs> clickAction)
{
var btn = new Button();
btn.OnClick += clickAction;
}
我希望这会有所帮助,如果没有,请告诉我。