Использование System.Reflection.Emit.ILGenerator для вызова Random в VB.Net?

Я генерирую вывод для исполняемого файла .Net с моего собственного языка ... код операции (называемый «Случайный»), который переводится с моего языка, должен создавать случайное число в определенном диапазоне.

Цель моего кода - создать случайное число с помощью класса System.Reflection.Emit.ILGenerator ... чтобы понять, как выглядит код CIL, я создал код vb.net:

Sub Main()
    Dim A As Random

    A = New Random

    Console.WriteLine(A.Next(100))
End Sub

Какой ILDASM сообщает как:

.method public static void  Main() cil managed
{
  .entrypoint
  .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       23 (0x17)
  .maxstack  2
  .locals init ([0] class [mscorlib]System.Random A)
  IL_0000:  nop
  IL_0001:  newobj     instance void [mscorlib]System.Random::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldc.i4.s   100
  IL_000a:  callvirt   instance int32 [mscorlib]System.Random::Next(int32)
  IL_000f:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_0014:  nop
  IL_0015:  nop
  IL_0016:  ret
} // end of method Main::Main

Я могу все воспроизвести с помощью метода ILGenerator.Emit; кроме строки IL_0001 ("newobj instance void [mscorlib] System.Random ::. ctor ()") ...

Надеюсь, я никого не завалил слишком большим количеством информации. Но я считаю, что лучше подробно описывать проблему, которая мне кажется сложной.

Наконец, у меня есть код, который я написал до сих пор:

 Sub EmitRandom()
    Dim NewRandom As New Random
    Dim stringtype As Type = GetType(System.Random)

    Dim paramtypes() As Type = {GetType(Integer)}, blankparams() As Type = {}
    'Dim RandomMethod = stringtype.GetMethod("New", paramtypes)

    m_ILGen.Emit(OpCodes.Newobj, New Random().GetType)

    EmitStoreInLocal(tempVariableRnd)
    EmitLoadLocal(tempVariableRnd)

    m_ILGen.Emit(OpCodes.Callvirt, stringtype.GetMethod("Next", paramtypes))
End Sub

Что испускает следующий код:

.
.
.
IL_0073:  newobj     [mscorlib]System.Random
IL_0078:  stloc.2
IL_0079:  ldloc.2
IL_007a:  callvirt   instance int32 [mscorlib]System.Random::Next(int32)
.
.
.

То, что я уже пробовал:

  • Придумывая способ указать IL_Gen.Emit (OpCodes.NewObj, ... ctor ()) ... не могу понять, как это сделать.

  • Придумываем способ указать на New () - поскольку, похоже, это то, чем является .ctor () ... New нельзя использовать как что-либо, кроме инициализатора.

  • Просто отключите функцию Random, пока я не найду лучший способ испускания.

Проблема кажется мне сложной, но я знаю, что есть кто-то, кто разбирается в генерации кода и MSIL легче, чем я, и кто готов указать ответ.

Спасибо за ваше время,

Доминик


person Dominick    schedule 11.06.2011    source источник
comment
Просто помните, что если вы каждый раз будете создавать новый Random, вы получите ужасную производительность и низкую случайность.   -  person skolima    schedule 12.06.2011


Ответы (1)


Вам нужно использовать ConstructorInfo:

 m_ILGen.Emit(OpCodes.Newobj, GetType(Random).GetConstructor(Type.EmptyTypes))

Также - хранение и загрузка из локального не нужны. Вам действительно нужен эквивалент new Random (). Next (100), не так ли? ... в этом случае сохранение и загрузка из локального никогда не происходит.

person Jeff    schedule 11.06.2011
comment
Одна строчка кода изменила мой день. Спасибо JennN825. - person Dominick; 12.06.2011