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);
我正在使用 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);