Reputation: 6281
I'm currently working with a struct which is written into a buffer. When reading the struct back into my Application i get the following exception:
Unable to cast object of type 'System.Windows.Documents.TextStore' to type 'System.Version'.
The exception is thrown when casting the result back ( (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;
}
}
Upvotes: 0
Views: 207
Reputation: 942408
Cooking your own binary serialization scheme with this approach is okay but you have to understand the limitations. And a core one is that it can only work on blittable values, simple value type values. The pinvoke marshaller has a workaround for strings with the [MarshalAs] attribute. No such workaround is available for the Version class. The pointer value stored in the struct is going to get written to the file. When you read it back, the more normal mishap is that you'll get an AccessViolationException. Unless you have the fortune that the pointer happens to dereference a valid object stored on the GC heap. An object of type TextStore in your case.
That's not exactly being lucky of course. You'll have to re-think your approach, the _Version field has to go. Do not hesitate to use the BinaryFormatter class, this is exactly what it was made to do.
Upvotes: 2