Home All Groups Group Topic Archive Search About

A little help with Reflection.Emit and TypeBuilder.GetMethod...

Author
2 Jun 2006 12:16 AM
GhostInAK
Good morning newsgroup!

Brief description:
I am creating a dynamic assembly.  I have a class with has some properties.
These properties have data types of classes which exist in the dynamic assembly.
The class has a dynamic method in which I would like to reference the properties
within the class.

My problem is explained at the very end...
I'll present the code as it looks if typed in the IDE (both VB and IL), and
then below I'll present my dynamic code gen function (in VB):

Excerpt VB Code:
    Private oSignalDetections As SignalDetectionCollection = New SignalDetectionCollection
    Private oSupportBlock As SupportBlock151 = New SupportBlock151

#Region " Heavy Lifting "

    Public Overrides Sub AssignBlocks(ByVal tBlocks As BlockCollection)

        SetBlockBasics(tBlocks(0), Me.AdminBlock)
        SetBlockBasics(tBlocks(1), Me.SignalDetections)
        SetBlockBasics(tBlocks(2), Me.SupportBlock)

    End Sub

#End Region




Translated to IL via ILDASM:
..method public strict virtual instance void
        AssignBlocks(class RCCAlertParser.BlockCollection tBlocks) cil managed
{
  // Code size       111 (0x6f)
  .maxstack  3
  .locals init ([0] class RCCAlertParser.IBlock _Vb_t_ref_0)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  ldarg.1
  IL_0003:  ldc.i4.0
  IL_0004:  callvirt   instance class RCCAlertParser.Block RCCAlertParser.BlockCollection::get_Item(int32)
  IL_0009:  ldarg.0
  IL_000a:  callvirt   instance class RCCAlertParser.AdministrativeBlock
RCCAlertParser.Alert::get_AdminBlock()
  IL_000f:  stloc.0
  IL_0010:  ldloca.s   _Vb_t_ref_0
  IL_0012:  callvirt   instance void RCCAlertParser.Alert::SetBlockBasics(class
RCCAlertParser.IBlock,

class RCCAlertParser.IBlock&)
  IL_0017:  nop
  IL_0018:  ldarg.0
  IL_0019:  ldloc.0
  IL_001a:  castclass  RCCAlertParser.AdministrativeBlock
  IL_001f:  callvirt   instance void RCCAlertParser.Alert::set_AdminBlock(class
RCCAlertParser.AdministrativeBlock)
  IL_0024:  nop
  IL_0025:  ldarg.0
  IL_0026:  ldarg.1
  IL_0027:  ldc.i4.1
  IL_0028:  callvirt   instance class RCCAlertParser.Block RCCAlertParser.BlockCollection::get_Item(int32)
  IL_002d:  ldarg.0
  IL_002e:  callvirt   instance class RCCAlertParser.SignalDetectionCollection
RCCAlertParser.Alert151::get_SignalDetections()
  IL_0033:  stloc.0
  IL_0034:  ldloca.s   _Vb_t_ref_0
  IL_0036:  callvirt   instance void RCCAlertParser.Alert::SetBlockBasics(class
RCCAlertParser.IBlock,

class RCCAlertParser.IBlock&)
  IL_003b:  nop
  IL_003c:  ldarg.0
  IL_003d:  ldloc.0
  IL_003e:  castclass  RCCAlertParser.SignalDetectionCollection
  IL_0043:  callvirt   instance void RCCAlertParser.Alert151::set_SignalDetections(class
RCCAlertParser.SignalDetectionCollection)
  IL_0048:  nop
  IL_0049:  ldarg.0
  IL_004a:  ldarg.1
  IL_004b:  ldc.i4.2
  IL_004c:  callvirt   instance class RCCAlertParser.Block RCCAlertParser.BlockCollection::get_Item(int32)
  IL_0051:  ldarg.0
  IL_0052:  callvirt   instance class RCCAlertParser.SupportBlock151 RCCAlertParser.Alert151::get_SupportBlock()
  IL_0057:  stloc.0
  IL_0058:  ldloca.s   _Vb_t_ref_0
  IL_005a:  callvirt   instance void RCCAlertParser.Alert::SetBlockBasics(class
RCCAlertParser.IBlock,

class RCCAlertParser.IBlock&)
  IL_005f:  nop
  IL_0060:  ldarg.0
  IL_0061:  ldloc.0
  IL_0062:  castclass  RCCAlertParser.SupportBlock151
  IL_0067:  callvirt   instance void RCCAlertParser.Alert151::set_SupportBlock(class
RCCAlertParser.SupportBlock151)
  IL_006c:  nop
  IL_006d:  nop
  IL_006e:  ret
} // end of method Alert151::AssignBlocks




DYNAMIC CODE GEN:
Private Sub BuildAssignBlocksPart(ByRef tTypeBuilder As TypeBuilder, ByRef
tILGenerator As ILGenerator, ByVal tBlockIndex As Int32, ByVal tPropertyType
As Type, ByVal tPropertyName As String)

        Dim tBaseMethod As MethodInfo = Nothing

        With tILGenerator
            .Emit(OpCodes.Nop)
            .Emit(OpCodes.Ldarg_0)
            .Emit(OpCodes.Ldarg_1)
            .Emit(OpCodes.Ldc_I4, tBlockIndex)
            tBaseMethod = GetType(BlockCollection).GetMethod("get_Item")
            .Emit(OpCodes.Callvirt, tBaseMethod)
            .Emit(OpCodes.Ldarg_0)
            tBaseMethod = tTypeBuilder.GetMethod("get_" & tPropertyName)
            .Emit(OpCodes.Callvirt, tBaseMethod)
            .Emit(OpCodes.Stloc_0)
            .Emit(OpCodes.Ldloca_S, 0)
            tBaseMethod = tTypeBuilder.GetMethod("SetBlockBasics")
            .Emit(OpCodes.Callvirt, tBaseMethod)
            .Emit(OpCodes.Nop)
            .Emit(OpCodes.Ldarg_0)
            .Emit(OpCodes.Ldloc_0)
            .Emit(OpCodes.Castclass, tPropertyType)
            tBaseMethod = tTypeBuilder.GetMethod("set_" & tPropertyName)
            .Emit(OpCodes.Callvirt, tBaseMethod)
        End With

    End Sub



The code above fails at:  tBaseMethod = tTypeBuilder.GetMethod("get_" & tPropertyName)
Note that the type represented by tTypeBuilder is dynamic (it was created
earlier in the assembly building process) and is part of the same assembly
that this code gen is trying to write to.

The exact exception is:
An unhandled exception of type 'System.NotSupportedException' occurred in
mscorlib.dll

Additional information: The invoked member is not supported in a dynamic
module.


So... how would one go about this?

Thanks in advance,
-Dan

AddThis Social Bookmark Button