症状
当面向 Microsoft .NET Framework 4.5.1 或 Microsoft .NET Framework 4.5.2 的代码动态绑定到方法 (时,例如,使用 Windows PowerShell、IronPython、IronRuby 或其他动态语言中的脚本) 调用 System.Runtime.InteropServices.Marshal.SizeOf 方法或System.Runtime.InteropServices.Marshal.PtrToStructure 方法可能会遇到以下问题。
注意 已编译为托管可执行文件的代码不会显示这些问题,除非该代码使用 C# 中的动态关键字 (keyword) 。
问题 1
对 System.Runtime.InteropServices.Marshal.SizeOf 的调用将引发以下 MethodInvocationException 异常:
注意
类型“类型名称>”<不能作为非托管结构进行封送;无法计算有意义的大小或偏移量。
问题 2
对 System.Runtime.InteropServices.Marshal.PtrToStructure 的调用将引发以下 MethodInvocationException 异常:
注意
指定的结构必须是 blittable 或具有布局信息。
问题 3
对 System.Runtime.InteropServices.Marshal.PtrToStructure 的调用将引发以下 RuntimeBinderException 异常:
注意
无法将类型“void”隐式转换为“object”。
原因
出现此问题的原因是脚本引擎和动态语言可能会绑定到.NET Framework中引入的新重载。 具体而言,以前使用 Marshal.SizeOf (Type) 的调用现在可能调用 Marshal.SizeOf<T> (T) ,而使用 Marshal.PtrToStructure (IntPtr、Type) 的调用现在可能调用 Marshal.PtrToStructure<T> (IntPtr, T) 。 此更改会导致方法或运行时绑定器引发异常。
解决方法
若要解决此问题,请更改代码,以便在语言允许的情况下使用正确的重载。 如果无法指定特定方法重载,请更改代码,使其正确使用新方法重载。
对于 C# 动态调用
在对 SizeOf 或 PtrToStructure 方法的调用中添加到 System.Type 的强制转换。 例如:
object obj = System.Runtime.InteropServices.Marshal.PtrToStructure(ptr, (System.Type)type);
int size = System.Runtime.InteropServices.Marshal.SizeOf((System.Type)type);
注意 仅当方法的其中一个参数是动态时,才需要执行此操作。
对于Windows PowerShell脚本
在对 SizeOf 或 PtrToStructure 方法的调用中添加到 System.Type 的强制转换。 例如:
$size = [System.Runtime.InteropServices.Marshal]::SizeOf([System.Type] $type)
$obj = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ptr, [System.Type] $type)
对于 IronPython 脚本
创建类型的新类型实例,然后使用新方法重载。 例如:
typeInstance = type()
size = System.Runtime.InteropServices.Marshal.SizeOf(typeInstance)
obj = System.Runtime.InteropServices.Marshal.PtrToStructure(ptr, typeInstance)
状态
Microsoft 已确认在 "适用于" 部分中所列的 Microsoft 产品中存在问题。