Ich habe Code wie diesen, um IL-Code zu emittieren, der Integer- oder String-Werte lädt. Aber ich weiß nicht, wie man dazu den decimal
Typ hinzufügt. Es wird in der Emit
Methode nicht unterstützt. Irgendwelche Lösungen dazu?Auslösen von IL-Code zum Laden eines Dezimalwerts
ILGenerator ilGen = methodBuilder.GetILGenerator();
if (type == typeof(int))
{
ilGen.Emit(OpCodes.Ldc_I4, Convert.ToInt32(value, CultureInfo.InvariantCulture));
}
else if (type == typeof(double))
{
ilGen.Emit(OpCodes.Ldc_R8, Convert.ToDouble(value, CultureInfo.InvariantCulture));
}
else if (type == typeof(string))
{
ilGen.Emit(OpCodes.Ldstr, Convert.ToString(value, CultureInfo.InvariantCulture));
}
Problem:
else if (type == typeof(decimal))
{
ilGen.Emit(OpCodes.Ld_???, Convert.ToDecimal(value, CultureInfo.InvariantCulture));
}
Edit: Okay, hier ist das, was ich getan habe:
else if (type == typeof(decimal))
{
decimal d = Convert.ToDecimal(value, CultureInfo.InvariantCulture);
// Source: https://msdn.microsoft.com/en-us/library/bb1c1a6x.aspx
var bits = decimal.GetBits(d);
bool sign = (bits[3] & 0x80000000) != 0;
byte scale = (byte)((bits[3] >> 16) & 0x7f);
ilGen.Emit(OpCodes.Ldc_I4, bits[0]);
ilGen.Emit(OpCodes.Ldc_I4, bits[1]);
ilGen.Emit(OpCodes.Ldc_I4, bits[2]);
ilGen.Emit(sign ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
ilGen.Emit(OpCodes.Ldc_I4, scale);
var ctor = typeof(decimal).GetConstructor(new[] { typeof(int), typeof(int), typeof(int), typeof(bool), typeof(byte) });
ilGen.Emit(OpCodes.Newobj, ctor);
}
Aber es erzeugt keine newobj
Opcode, sondern stattdessen nop
und stloc.0
. Der Konstruktor wird gefunden und an den Aufruf Emit
übergeben. Was ist hier falsch? Offensichtlich wird ein InvalidProgramException
geworfen, wenn versucht wird, den generierten Code auszuführen, da der Stapel vollständig durcheinander ist.
Anscheinend (aber nehmen Sie nicht mein Wort dafür) für „Last dezimal“ gibt es keine direkte Opcode, laden Sie die Argumente und rufen Sie den Dezimal-Konstruktor: siehe http : //stackoverflow.com/a/485834/266143 – CodeCaster
Siehe auch http://codeblog.jonskeet.uk/2014/08/22/when-is-a-constant-not-a-constant-when-its-a -Dezimal/. Kurz gesagt: Dezimale sind keine primitiven CLR-Typen und es gibt keinen IL-Opcode, um einen direkt zu laden. –
Siehe meine Bearbeitung oben für eine nicht funktionierende Lösung. – ygoe