In some scenarios, we may add more than one handler for a specific event. In this case, AutoCAD will throw it several times. Imagine a code like the one below, where for the Document object we add 2 handlers duplicated, and another different.
<CommandMethod("addEvents")> _
Public Sub CmdCheckEvents()
' get the document collection
' and add a few handlers
Dim doc As Document = Application. _
DocumentManager.MdiActiveDocument
' add handler 1
AddHandler doc.CommandEnded, _
AddressOf CustomCommandEnded1
' duplicate handler 1
AddHandler doc.CommandEnded, _
AddressOf CustomCommandEnded1
' add handler 2
AddHandler doc.CommandEnded, _
AddressOf CustomCommandEnded2
End Sub
' handler 1
Private Sub CustomCommandEnded1(sender As Object, _
e As CommandEventArgs)
Application.DocumentManager.MdiActiveDocument. _
Editor.WriteMessage("CMDEND_1")
End Sub
' handler 2
Private Sub CustomCommandEnded2(sender As Object, _
e As CommandEventArgs)
Application.DocumentManager.MdiActiveDocument _
.Editor.WriteMessage("CMDEND_2")
End Sub
As a result, the event will trigger duplicated for the handler 1 and again for the handler 2.
With .NET we can get the list of events and manipulate it using Reflection. This is not very direct, but can be achieved with the following code. Note that we have to be carefully to not remove handlers from other plug-ins, so skip those not defined on the current assembly.
<CommandMethod("removeEvents")> _
Public Sub CmdRemoveEvents()
Dim doc As Document = Application. _
DocumentManager.MdiActiveDocument
RemoveHandlers(doc, "CommandEnded")
End Sub
Public Sub RemoveHandlers(obj As Object, eventName As String)
' type of the object
Dim docType As Type = obj.GetType()
' get the event info
Dim eventInfo As EventInfo = docType.GetEvent(eventName)
' get all fields
Dim fields() As FieldInfo = docType.GetFields(
BindingFlags.Instance Or _
BindingFlags.Static Or _
BindingFlags.NonPublic Or _
BindingFlags.Public)
' find the field with the name we seek with LINQ.
' this assumes that the respective field has
' a name similar to the event
' e.g. CommandEnded field is m_pCommandEndedEvent
Dim eventFields As Object = From f In fields _
Where f.Name.Contains(eventInfo.Name) _
Select f
' get the field from the selection (first)
Dim eventField As FieldInfo = Nothing
For Each f In eventFields
eventField = f
Next
' in case nothing was found...
If (eventField Is Nothing) Then Exit Sub
' now the value of the field
Dim eventDelegate As [Delegate] = eventField.GetValue(obj)
' finally all the handlers added to the event
Dim handlers As [Delegate]() = eventDelegate.GetInvocationList()
' iterate through the collection of handlers
For Each handler As [Delegate] In handlers
' get the type of the handler, so we can skip internal handlers
Dim handlerType As Type = handler.Target.GetType()
' only handlers defined on this custom assembly
If (handlerType.Assembly = _
System.Reflection.Assembly. _
GetExecutingAssembly()) Then
' finally remove the handler
eventInfo.RemoveEventHandler(obj, handler)
End If
Next
End Sub