【问题标题】:Cast exception when marshalling编组时抛出异常
【发布时间】:2012-04-18 09:53:46
【问题描述】:

我目前正在处理一个写入缓冲区的结构。将结构读回我的应用程序时,出现以下异常:

无法将“System.Windows.Documents.TextStore”类型的对象转换为“System.Version”类型。

代码

将结果转换回 ((T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));) 时会引发异常。

protected static T ReadStruct<T>(Stream input)
    where T : struct
{
    Byte[] buffer = new Byte[Marshal.SizeOf(typeof(T))];
    input.Read(buffer, 0, buffer.Length);
    GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
    T result = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
    handle.Free();
    return result;
}

使用的数据结构

/// <summary>
/// The header for all binary files
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet=CharSet.Ansi)]
public unsafe struct BinaryHeader
{
    public const String MAGIC_KEY = "TABF";

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)]
    String _Magic;
    Version _Version;
    DateTime _Timestamp;
    Guid _Format;
    Int64 _Reserved0;
    Int64 _Reserved1;
    /// <summary>
    /// The magic value for the test automation binary
    /// </summary>
    public String Magic
    {
        get
        {
            return _Magic;
        }
    }
    /// <summary>
    /// The version of the assembly ( used for debugging )
    /// </summary>
    public Version AssemblyVersion { get { return _Version; } }
    /// <summary>
    /// The formatGuid of the current binary
    /// </summary>
    public Guid FormatGuid { get { return _Format; } }
    /// <summary>
    /// The timestamp of the file
    /// </summary>
    public DateTime Timestamp { get { return _Timestamp; } }

    public BinaryHeader(Guid formatGuid)
    {
        _Reserved0 = 0;
        _Reserved1 = 0;

        _Version = BinaryBase.AssemblyVersion;
        _Format = formatGuid;
        _Timestamp = DateTime.Now;
        _Magic = MAGIC_KEY;
    }
}

【问题讨论】:

    标签: c# marshalling


    【解决方案1】:

    使用这种方法制作自己的二进制序列化方案是可以的,但您必须了解其局限性。一个核心是它只能处理 blittable 值,简单的值类型值。 pinvoke marshaller 为具有 [MarshalAs] 属性的字符串提供了一种解决方法。版本 class 没有这样的解决方法。存储在结构中的指针值将被写入文件。当你回读它时,更正常的事故是你会得到一个 AccessViolationException。除非你有幸指针碰巧取消引用存储在 GC 堆上的有效对象。在您的情况下为 TextStore 类型的对象。

    当然,这并不完全是幸运。您必须重新考虑您的方法,_Version 字段必须删除。不要犹豫,使用 BinaryFormatter 类,这正是它的目的。

    【讨论】:

    • 谢谢,我没有注意到 Version 实际上是一个类,我以为它是一个值类型。使用该结构来保存很多代码行,因为我有很多数据要序列化,对于其他情况,我使用的是 BinaryFormatter。谢谢。
    猜你喜欢
    • 2013-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-24
    • 2019-12-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多