Imports System.Reflection
Imports System.Reflection.Emit
' These classes are for demonstration purposes.
'
Public Class Base
Public Number As Integer = 0
Public Sub New(ByVal initialNumber As Integer)
Number = initialNumber
End Sub
End Class
Public Class DerivedFromBase
Inherits Base
Public Sub New(ByVal initialNumber As Integer)
MyBase.New(initialNumber)
End Sub
End Class
' Two delegates are declared: UseLikeInstance treats the dynamic
' method as if it were an instance method, and UseLikeStatic
' treats the dynamic method in the ordinary fashion.
'
Public Delegate Function UseLikeInstance(ByVal number As Integer) _
As Integer
Public Delegate Function UseLikeStatic(ByVal b As Base, _
ByVal number As Integer) As Integer
Public Class Example
Public Shared Sub Demo(ByVal outputBlock As System.Windows.Controls.TextBlock)
' This dynamic method sets the public Number field of an instance
' of Base, and returns the previous value. The method has no name.
' It takes two parameters, an instance of Base and an Integer that
' is the new field value.
'
Dim changeNumber As New DynamicMethod( _
"", _
GetType(Integer), _
New Type() {GetType(Base), GetType(Integer)} _
)
' Get a FieldInfo for the public field 'Number'.
Dim fnum As FieldInfo = GetType(Base).GetField( _
"Number", _
BindingFlags.Public Or BindingFlags.Instance _
)
Dim ilg As ILGenerator = changeNumber.GetILGenerator()
' Push the current value of the Number field onto the
' evaluation stack. It's an instance field, so load the
' instance of Base before accessing the field.
ilg.Emit(OpCodes.Ldarg_0)
ilg.Emit(OpCodes.Ldfld, fnum)
' Load the instance of Base again, load the new value
' of id, and store the new field value.
ilg.Emit(OpCodes.Ldarg_0)
ilg.Emit(OpCodes.Ldarg_1)
ilg.Emit(OpCodes.Stfld, fnum)
' The original value of the Number field is now the only
' thing on the stack, so return from the call.
ilg.Emit(OpCodes.Ret)
' Create a delegate that uses changeNumber in the ordinary
' way, as a static method that takes an instance of
' Base and an Integer.
'
Dim uls As UseLikeStatic = CType( _
changeNumber.CreateDelegate(GetType(UseLikeStatic)), _
UseLikeStatic _
)
' Create an instance of Base with an id of 42.
'
Dim ba As New Base(42)
' Create a delegate that is bound to the instance of
' of Base. This is possible because the first
' parameter of changeNumber is of type Base. The
' delegate has all the parameters of changeNumber except
' the first.
Dim uli As UseLikeInstance = CType( _
changeNumber.CreateDelegate( _
GetType(UseLikeInstance), _
ba), _
UseLikeInstance _
)
' First, change the value of Number by calling changeNumber as
' a static method, passing in the instance of Base.
'
outputBlock.Text &= String.Format( _
"Change the value of Number; previous value: {0}", _
uls(ba, 1492) _
) & vbCrLf
' Change the value of Number again using the delegate
' bound to the instance of Base.
'
outputBlock.Text &= String.Format( _
"Change the value of Number; previous value: {0}", _
uli(2700) _
) & vbCrLf
outputBlock.Text &= String.Format("Final value of Number: {0}", ba.Number) & vbCrLf
' Now repeat the process with a class that derives
' from Base.
'
Dim dfba As New DerivedFromBase(71)
uli = CType( _
changeNumber.CreateDelegate( _
GetType(UseLikeInstance), _
dfba), _
UseLikeInstance _
)
outputBlock.Text &= String.Format( _
"Change the value of Number; previous value: {0}", _
uls(dfba, 73) _
) & vbCrLf
outputBlock.Text &= String.Format( _
"Change the value of Number; previous value: {0}", _
uli(79) _
) & vbCrLf
outputBlock.Text &= String.Format("Final value of Number: {0}", dfba.Number) & vbCrLf
End Sub
End Class
' This example produces the following output:
'
'Change the value of Number; previous value: 42
'Change the value of Number; previous value: 1492
'Final value of Number: 2700
'Change the value of Number; previous value: 71
'Change the value of Number; previous value: 73
'Final value of Number: 79'