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.
_ 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.
_ 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


Leave a Reply to Tony TanzilloCancel reply