Utilizzando System.Reflection.Emit.ILGenerator chiamare a caso in VB.Net?
-
26-10-2019 - |
Domanda
Sto generazione di output per un .Net eseguibile dalla mia lingua ... il codice operativo (chiamato 'a caso') che viene tradotto da mia lingua si suppone di creare un numero casuale all'interno di una gamma specifica.
L'obiettivo per il mio codice è quello di produrre il numero casuale utilizzando la classe System.Reflection.Emit.ILGenerator ... per capire come gli sguardi di codice CIL ho creato un certo codice vb.net:
Sub Main()
Dim A As Random
A = New Random
Console.WriteLine(A.Next(100))
End Sub
Quali ILDASM segnala come:
.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
I grado di riprodurre tutto utilizzando il metodo ILGenerator.Emit; tranne la linea ( "newobj esempio void [mscorlib] System.Random ::. ctor ()") IL_0001 ...
Speriamo che non ho travolto chiunque con troppe informazioni. Ma immagino che sia meglio essere prolisso quando si descrive un problema che sembra complesso a me.
Finalmente ho il codice che ho prodotto finora:
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
che emette il seguente codice:
.
.
.
IL_0073: newobj [mscorlib]System.Random
IL_0078: stloc.2
IL_0079: ldloc.2
IL_007a: callvirt instance int32 [mscorlib]System.Random::Next(int32)
.
.
.
Le cose che ho provato già :
-
Venendo con un modo per puntare IL_Gen.Emit (OpCodes.NewObj, ... ctor ()) ... non può capire come.
-
venire con un modo per scegliere Nuovo () - dal momento che sembra essere quello .ctor () è ... Nuova non può essere utilizzato se non come un inizializzatore
-
Proprio disabilitando la funzione Random fino a quando posso venire con un modo migliore di emettere.
Il problema sembra difficile per me, ma so che c'è qualcuno là fuori che capisce la generazione di codice MSIL e più facilmente di me e che è disposto a sottolineare una risposta.
Grazie per il vostro tempo,
Dominick
Soluzione
È necessario utilizzare il ConstructorInfo:
m_ILGen.Emit(OpCodes.Newobj, GetType(Random).GetConstructor(Type.EmptyTypes))
Inoltre - lo stoccaggio e il caricamento da quello locale sono inutili. Davvero vuole solo l'equivalente di new Random (). Avanti (100), giusto? ... nel qual caso lo stoccaggio e il caricamento da un locale non accade mai.