En utilisant System.Reflection.Emit.ILGenerator pour appeler au hasard dans VB.Net?
-
26-10-2019 - |
Question
Je suis sortie pour générer un exécutable .Net de ma propre langue ... l'opcode (appelé « aléatoire ») qui est en cours de traduction de ma langue est censé créer un nombre aléatoire dans une plage spécifique.
Le but de mon code est de produire le nombre aléatoire en utilisant la classe System.Reflection.Emit.ILGenerator ... pour comprendre comment le code CIL apparence que j'ai créé un code de vb.net:
Sub Main()
Dim A As Random
A = New Random
Console.WriteLine(A.Next(100))
End Sub
Ce qui ILDASM rapporte que:
.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
Je peux tout reproduire en utilisant la méthode ILGenerator.Emit; excepter la ligne IL_0001 ( "vide instance newobj [mscorlib] System.Random ::. cteur ()") ...
Si tout va bien, je ne l'ai pas dépassé tout le monde avec trop d'informations. Mais je dis qu'il vaut mieux être bavard pour décrire un problème qui me semble complexe.
Enfin, j'ai le code que j'ai produit jusqu'à présent:
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
Ce qui émet le code suivant:
.
.
.
IL_0073: newobj [mscorlib]System.Random
IL_0078: stloc.2
IL_0079: ldloc.2
IL_007a: callvirt instance int32 [mscorlib]System.Random::Next(int32)
.
.
.
Les choses que j'ai déjà essayé :
-
Venir avec un moyen de pointer IL_Gen.Emit (OpCodes.NewObj, ... cteur ()) ... ne peut pas comprendre comment.
-
Venir avec un moyen de pointez sur Nouveau () - puisque cela semble être ce que .ctor () est ... Nouveau ne peut pas être utilisé comme tout sauf un initialiseur
-
Il suffit de désactiver la fonction aléatoire jusqu'à ce que je peux trouver une meilleure façon d'émettre.
Le problème semble difficile pour moi, mais je sais qu'il ya quelqu'un là-bas qui comprend la génération de code et MSIL plus facilement que moi et qui est prêt à signaler une réponse.
Merci pour votre temps,
Dominick
La solution
Vous devez utiliser le ConstructorInfo:
m_ILGen.Emit(OpCodes.Newobj, GetType(Random).GetConstructor(Type.EmptyTypes))
Aussi - le stockage et le chargement du local ne sont pas nécessaires. Vous voulez vraiment que l'équivalent de new Random (). Ensuite (100), à droite? ... dans ce cas, le stockage et le chargement d'une jamais locale passe.