MSIL 将结构值存储到 return

MSIL store a value of structure to return

我正在使用 RemotingLite 库 (see at github) 并且 Proxy class 工厂有问题。 简而言之,问题是在为 return 和 ValueType 对象(如用户定义的结构)生成代码时。

部分原代码如下:

...
mIL.Emit(OpCodes.Ldloc, resultLB.LocalIndex); //load the result array
mIL.Emit(OpCodes.Ldc_I4, 0); //load the index of the return value. Alway 0
mIL.Emit(OpCodes.Ldelem_Ref); //load the value in the index of the array

if (returnType.IsValueType)
{
    mIL.Emit(OpCodes.Unbox, returnType); //unbox it
    mIL.Emit(ldindOpCodeTypeMap[returnType]);
}
else
    mIL.Emit(OpCodes.Castclass, returnType);
}
        mIL.Emit(OpCodes.Ret);

ldindOpCodeTypeMap 是一个带有 OpCodes.Ldind_U2 等操作码的字典。因此它仅适用于 Int16, Int32 等标准 MSIL 类型。但是如果我需要推送,我需要做什么堆叠然后 return 自定义 ValueType 值(例如 - Guid - 大小为 16 字节)?

例如:

...
mIL.Emit(OpCodes.Unbox, returnType); //unbox it
OpCode opcode;
if (ldindOpCodeTypeMap.TryGetValue(returnType, out opcode))
{
    mIL.Emit(ldindOpCodeTypeMap[returnType]);
}
else
{
    // here I getting the size of custom type
    var size = System.Runtime.InteropServices.Marshal.SizeOf(returnType);
    // what next?
}
...

这里我得到了一个自定义尺寸 ValueType 值。那么如何像 Ldind_x 操作码那样将自定义 ValueType 的值间接加载到评估堆栈上呢? 谢谢!

Ldobj 会为所欲为。但是您也可以将整个条件替换为 Unbox_Any:它将完成您需要的值类型或引用类型的所有操作。

您发布的代码的完整替换为:

...
mIL.Emit(OpCodes.Ldloc, resultLB.LocalIndex); //load the result array
mIL.Emit(OpCodes.Ldc_I4, 0); //load the index of the return value. Alway 0
mIL.Emit(OpCodes.Ldelem_Ref); //load the value in the index of the array

mIL.Emit(OpCodes.Unbox_Any, returnType);
mIL.Emit(OpCodes.Ret);