我有一个班级' oBnd'定义为Object,可以指定为clsBound或clsClaim类型。 索赔和约束从外部,相同的方法等相同。
我使用' CallByName'来调用各种属性
即Dim Current As String = CallByName(oBnd, PropName, CallType.Get)
当在任一类中更改属性时,该类会引发DirtyStatus事件。
我在附加此事件时遇到问题。
如果我尝试
AddHandler oBnd.DirtyStatus, AddressOf oBnd_DirtyStatus
我收到错误" DirtyStatus不是Object"我想这是有道理的,因为很明显对象对我的脏状态一无所知。
我尝试使用:
AddHandler DirectCast(oBnd, clsBound).DirtyStatus, AddressOf oBnd_DirtyStatus
虽然这确实修复了错误,但是在引发DirtyStatus事件时它不会被调用。
oBnd定义为
Private WithEvents oBnd As Object
它是全球形式的
oBnd设置为
oBnd = New clsBound(mvarBUDConnection)
AddHandler oBnd.DirtyStatus, AddressOf oBnd_DirtyStatus
oBnd.Load(CInt(txtTrans.Text))
BuildPage(oBnd)
或者
oBnd = New clsClaim(mvarBUDConnection)
AddHandler oBnd.DirtyStatus, AddressOf oBnd_DirtyStatus
oBnd.Load(CInt(txtTrans.Text))
BuildPage(oBnd)
我想附加的oBnd_DirtyStatus子,看起来像这样
Private Sub oBnd_DirtyStatus(IsDirty As Boolean) ' Handles oBnd.DirtyStatus
Me.Text = "QFix"
If IsDirty Then
Me.Text = "QFix - Pending Save"
btnSave.Enabled = True
Else
btnSave.Enabled = False
End If
End Sub
如何附加此事件的句柄?
答案 0 :(得分:1)
以下是如何使事件工作并远离使用Reflection访问属性。即使给定the public methods are similar but the data being carried is very different
,仍然可以使用OOP /继承。
Public Enum ClaimBoundType
None ' error!!!!
Claim
Bound
End Enum
Public MustInherit Class ClaimBase
' type tracker usually rather handy
Public Property ItemType As ClaimBoundType
Public Sub New(t As ClaimBoundType)
ItemType = t
End Sub
' low rent INotifyPropertyChanged
Public Event DataChanged(sender As Object, e As EventArgs)
' "universal" prop: works the same for all derived types
Private _name As String = ""
Public Property Name As String
Get
Return _name
End Get
Set(value As String)
If value <> _name Then
_name = value
BaseDataChanged(Me)
End If
End Set
End Property
' props which must be implemented; 1 or 100 doesnt matter
MustOverride Property CurrentValue As Integer
' methods which must be implemented
MustOverride Function DoSomething() As Integer
' raise the changed event for base or derived classes
Protected Friend Sub BaseDataChanged(sender As Object)
RaiseEvent DataChanged(sender, New EventArgs())
End Sub
End Class
您必须进行一些基本的数据分析,以确定哪些属性和方法可以在基类中实现(与上面的Name
一样)以及继承的类中的哪些属性和方法。通常至少有一些可以在基类中完成。
您的派生类可以用完全不同的方式实现方法,并从以下任何地方加载数据:
Public Class Claim
Inherits ClaimBase ' the IDE will add all the MustInherits when
' you press enter
Public Sub New()
MyBase.New(ClaimBoundType.Claim)
End Sub
Public Overrides Function DoSomething() As Integer
' what happens here can be completely different
' class to class
End Function
Private _CurValue As Integer = 0
Public Overrides Property CurrentValue As Integer
Get
Return _CurValue
End Get
Set(Value As Integer)
If _CurValue <> Value Then
_CurValue = Value
OnDataChanged("CurrentValue")
End If
End Set
End Property
' name of prop that changed not actually used here, but
' is usually good to know (use custom args or INotifyPropertyChanged)
Public Sub OnDataChanged(pname As String)
' fire shared datachanged event
MyBase.BaseDataChanged(Me)
End Sub
End Class
现在您可以在不诉诸Object
的情况下实现它们,订阅事件而不必使用Reflection来获取/设置属性:
' 'generic' object variable: DONT/CANT USE [New] w/ClaimBase
Private myCB As ClaimBase
...
' set it as a Claim instance...
' This is perfectly legal because Claim is also a ClaimBase Type:
myCB = New Claim
' hook up the event handler
AddHandler myCB.DataChanged, AddressOf cb_DataChanged
您可以声明您的对象变量为ClaimBase
,但您无法创建ClaimBase
的实例,因为它是abstract
/ MustInherit
。由于事件是基类的一部分,因此语法没有问题。表单级处理程序:
' Use standard (sender, e) signature
' (CA will object to other signatures:)
Private Sub cb_DataChanged(sender As Object, e As EventArgs)
' do change stuff here
...
End Sub
最重要的是,您可以直接引用属性:
cbObj.Name = "Ziggy" ' will fire the event from the base class
cbObj.CurrentValue = 42 ' fires event from the Claim class
我添加了ItemType
属性,因此您可以在运行时区分它们(即当您将鼠标悬停在ClaimBase
对象变量上时)。如果/当有特定类型的属性/方法要访问时,将其强制转换(从你所说的,现在不能出现这些):
If cbObj.ItemType = ClaimBoundType.Claim Then
CType(cbObj, Claim).ClaimSomething = 5
End If
同样使用ClaimBase
作为Lists
的声明类型和方法签名也允许传递任一类型而不是装箱(转换为Object
):
Private cbList As New List(Of ClaimBase)
...
' just an example of the declaration
Private Sub AddThingToList(cb As ClaimBase)
cbList.Add(cb)
End Sub
我没有进入INotifyProperty
以便专注于继承,尽管它的基础是在该基类中。这是实现DataChanged / DirtyStatus事件和检测的更系统的方法。