Click here to Skip to main content
15,844,602 members
Articles / Programming Languages / Visual Basic

Dynamic Events in VB.NET

Rate me:
Please Sign up or sign in to vote.
4.52/5 (8 votes)
26 Mar 2013CPOL2 min read 38.6K   727   20   3
How to handle dynamic, late binding, events for COM objects in VB.NET.


This article shows a way to use events with late bound COM objects. To solve the problem some C# script was used...


There are two common ways in VB.NET to create a late bound object.

  • Using the CreateObject method.

    Dim ie As Object = CreateObject("InternetExplorer.Application")
  • Using the System.Activator.CreateInstance method.

    Dim iet As Type = Type.GetTypeFromProgID("InternetExplorer.Application")
    Dim ie As Object = Activator.CreateInstance(iet)

And there are three common ways in VB.NET to call methods and properties on a late bound object.

  • With Option Strict turned off

    ' call a method
    ' read a property
    Dim readyState As Integer = ie.ReadyState
    ' write a property
    ie.Visible = True
  • Using the Microsoft.VisualBasic.Interaction.CallByName method.

    ' Call a method 
    CallByName(ie, "Navigate", CallType.Method, "about:blank")
    ' Read a property
    readyState = CInt(CallByName(ie, "ReadyState", CallType.Get))
    ' Write a property
    CallByName(ie, "Visible", CallType.Let, True)
  • Using the System.Type.InvokeMember method.

    ' Call a method 
    ie.GetType().InvokeMember("Navigate", BindingFlags.InvokeMethod, Type.DefaultBinder, ie, {"about:blank"})
    ' Read a property
    readyState = CInt(ie.GetType().InvokeMember("ReadyState", BindingFlags.GetProperty, Type.DefaultBinder, ie, Nothing))
    ' Write a property
    ie.GetType().InvokeMember("Visible", BindingFlags.SetProperty, Type.DefaultBinder, ie, {True})

There are some ways discussed on how to use events with late bound objects, see Google search ' Eventhandler for late bound objects). But there isn't any way to add event handlers on late bound COM objects like with the dynamic Type in C#.

  • Working in C#

    public delegate void OnQuitDelegate();
    static void Main(string[] args)
        var iet = Type.GetTypeFromProgID("InternetExplorer.Application");
        dynamic ie = Activator.CreateInstance(iet);
        ie.OnQuit += new OnQuitDelegate(ie_OnQuit);
    public static void ie_OnQuit()
  • Not working in VB.NET

    Dim iet As Type = Type.GetTypeFromProgID("InternetExplorer.Application")
    ' No dynamic type...
    Dim ie = Activator.CreateInstance(iet)
    ' Not working...
    ' AddHandler ie.OnQuit, AddressOf ie_OnQuit
    ' Not working also...
    'ie.OnQuit += New OnQuitDelegate(AddressOf ie_OnQuit)

A first idea was to write a library in C# but the name of the event is hard coded. So that wasn't possible too, except ...It is when compiling C# script at runtime...

  • So first a interface was made to make calls into the compiled C# script.

    Public Interface IEventBinder
        Sub [AddHandler](ByVal source As Object, ByVal [delegate] As [Delegate])
        Sub [RemoveHandler](ByVal source As Object, ByVal [delegate] As [Delegate])
    End Interface
  • Then a class was written that implemented the interface with Factory methods that compiled and returned instances of the class/interface. From then on events could be attached to and detached from an object.

    Imports Microsoft.CSharp
    Imports System.CodeDom
    Imports System.CodeDom.Compiler
    Imports System.Reflection
    Imports System.Text
    Public NotInheritable Class EventBinder
        Implements IEventBinder
        Private _name As String
        Private _event As IEventBinder
        Private Sub New(ByVal name As String, ByVal [event] As IEventBinder)
            Me._name = name
            Me._event = [event]
        End Sub
        Public ReadOnly Property Name As String
                Return _name
            End Get
        End Property
        Public Sub [AddHandler](source As Object, [delegate] As System.Delegate) Implements IEventBinder.AddHandler
            Me._event.AddHandler(source, [delegate])
        End Sub
        Public Sub [RemoveHandler](source As Object, [delegate] As System.Delegate) Implements IEventBinder.RemoveHandler
            Me._event.RemoveHandler(source, [delegate])
        End Sub
        Public Shared Function CreateEventBinders(ByVal names() As String) As Dictionary(Of String, EventBinder)
            Using provider As CodeDomProvider = New CSharpCodeProvider()
                Dim parameters As New CompilerParameters() With {
                    .GenerateInMemory = True
                Dim uid As String = Guid.NewGuid().ToString("N")
                Dim code As New StringBuilder()
                    "using System;" & vbCrLf &
                    "" & vbCrLf &
                    "namespace DynamicEvent {" & vbCrLf
                For Each name As String In names
                            "public class {0}Event{2} : {1}.IEventBinder" & vbCrLf &
                            "{{" & vbCrLf &
                            "   public void AddHandler(dynamic source, Delegate del) {{ source.{0} += del; }}" & vbCrLf &
                            "   public void RemoveHandler(dynamic source, Delegate del) {{ source.{0} -= del; }}" & vbCrLf &
                            "}}" & vbCrLf,
                Dim codeResult As CompilerResults = provider.CompileAssemblyFromSource(parameters, code.ToString())
                If codeResult.Errors.Count = 0 Then
                    Dim result As New Dictionary(Of String, EventBinder)
                    For Each name As String In names
                        Dim codeType As Type = codeResult.CompiledAssembly.GetType(String.Format("DynamicEvent.{0}Event{1}", name, uid))
                        Dim codeObject As Object = Activator.CreateInstance(codeType)
                        result.Add(name, New EventBinder(name, DirectCast(codeObject, IEventBinder)))
                    Return result
                    ' todo: Compiler errors...
                    Return Nothing
                End If
            End Using
        End Function
        Public Shared Function CreateEventBinder(ByVal name As String) As EventBinder
            Return CreateEventBinders({name})(name)
        End Function
    End Class

Using the code

To attach an event now:

  • A delegate declaration is required.

    Delegate Sub OnQuitDelegate()
  • A event handler is required.

    Sub ie_OnQuit()
        ' ...
    End SUb	
  • A instance of the delegate is required.

    Dim [delegate] As [Delegate] = New OnQuitDelegate(AddressOf ie_OnQuit)
  • And a instance of EventBinder for the specific event is required.

    Dim binder As EventBinder = EventBinder.CreateEventBinder("OnQuit")
  • From then on it's possible to attach, detach events...

    Dim ie As Object = CreateObject("InternetExplorer.Application")
    binder.AddHandler(ie, [delegate])
    binder.RemoveHandler(ie, [delegate])

But it's better for performance to create the interfaces for all events at once. (Not that speed matters, this is VB.NET and has the speed of light...)

  • Bind to more then one event:
    ' Create event binders
    Dim binders As Dictionary(Of String, EventBinder)
    binders = EventBinder.CreateEventBinders({
    ' Create event handlers
    Dim delegates() As [Delegate] = {
        New BeforeNavigate2Delegate(AddressOf ie_BeforeNavigate2),
        New DocumentCompleteDelegate(AddressOf ie_DocumentComplete),
        New NavigateComplete2Delegate(AddressOf ie_NavigateComplete2),
        New OnQuitDelegate(AddressOf ie_OnQuit),
        New StatusTextChangeDelegate(AddressOf ie_StatusTextChange)
    ' Bondage...
    For i As Integer = 0 To binders.Count - 1
        binders(binders.Keys(i)).AddHandler(ie, delegates(i))


  • 18/03/2013: First draft.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Written By
Software Developer
Belgium Belgium
Currently i work in a small company making software for windows mobile. I have to be very "all-round" working in C++, VB.Net, VBScript and WinDev.

This i do for Windows, Web and Mobile development.

Learning new things is what i like to do most, improving my style and attitude TID!

Comments and Discussions

GeneralMy vote of 5 Pin
Ștefan-Mihai MOGA12-Apr-13 20:14
professionalȘtefan-Mihai MOGA12-Apr-13 20:14 
This is a great inspiring article. I am pretty much pleased with your good work. You put really very helpful information. Keep it up once again.
GeneralMy vote of 5 Pin
Member 373058726-Mar-13 3:02
Member 373058726-Mar-13 3:02 
GeneralRe: My vote of 5 Pin
Vozzie226-Mar-13 9:30
Vozzie226-Mar-13 9:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.