我有这样的代码来发送加载整数或字符串值的IL代码。但我不知道如何添加decimal
类型。它在Emit
方法中不受支持。任何解决方案?发送IL代码来加载一个十进制值
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));
}
不工作:
else if (type == typeof(decimal))
{
ilGen.Emit(OpCodes.Ld_???, Convert.ToDecimal(value, CultureInfo.InvariantCulture));
}
编辑:好了,这里就是我所做的:
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);
}
但它不会产生newobj
操作码,但而不是nop
和stloc.0
。找到构造函数并将其传递给Emit
调用。这里有什么问题?很显然,当试图执行生成的代码时会抛出一个InvalidProgramException
,因为堆栈是完全混乱的。
显然,(但不要把我的话)的“负载十进制”没有直接的操作码,您加载参数并调用构造函数小数:请参阅http ://stackoverflow.com/a/485834/266143 – CodeCaster
另请参阅http://codeblog.jonskeet.uk/2014/08/22/when-is-a-constant-not-a-constant-when-its-a -decimal /。简而言之:小数不是CLR原始类型,并且没有用于直接加载一个的IL操作码。 –
请参阅上面的我的编辑,了解非工作解决方案。 – ygoe