0

私は現在、バッファに書き込まれる構造体を使用しています。構造体をアプリケーションに読み戻すと、次の例外が発生します。

タイプ'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;
    }
}
4

1 に答える 1

2

このアプローチで独自のバイナリシリアル化スキームを作成することは問題ありませんが、制限を理解する必要があります。そして、核となるのは、ブリット可能な値、単純な値型の値でしか機能しないということです。pinvokeマーシャラーには、[MarshalAs]属性を持つ文字列の回避策があります。Versionクラスでは、このような回避策はありません。構造体に格納されているポインタ値がファイルに書き込まれます。読み返してみると、より一般的な事故は、AccessViolationExceptionが発生することです。ポインタがGCヒープに格納されている有効なオブジェクトを間接参照するという幸運がない限り。あなたの場合、タイプTextStoreのオブジェクト。

もちろん、それは必ずしも幸運ではありません。あなたはあなたのアプローチを再考する必要があるでしょう、_Versionフィールドは行かなければなりません。BinaryFormatterクラスを使用することを躊躇しないでください、これはまさにそれが行われたことです。

于 2012-04-18T14:27:36.053 に答える