The .NET 4.0 Framework introduces classes for reading and writing memory mapped files. The classes are centred around methods for reading and writing structures. These are not marshalled but copied from and to the file in the form in which they are laid out in managed memory.
Let's say I want to write two structures sequentially to a memory mapped file using these methods:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Foo
{
public char C;
public bool B;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Bar
{
}
static void Write<T1, T2>(T1 item1, T2 item2)
where T1 : struct
where T2 : struct
{
using (MemoryMappedFile file = MemoryMappedFile.CreateNew(null, 32))
using (MemoryMappedViewAccessor accessor = file.CreateViewAccessor())
{
accessor.Write<T1>(0L, ref item1); // <-- (1)
accessor.Write<T2>(??, ref item2); // <-- (2)
}
}
static void Main()
{
Foo foo = new Foo { C = 'α', B = true };
Bar bar = new Bar { };
Write(foo, bar);
}
How would I get the number of bytes written in (1) so I can write the next value adjacently in (2)?
Note: The number of bytes in the example is 3(=2+1), not 5(=1+4) as returned by Marshal.SizeOf.
Note 2: sizeof
cannot determine the size of generic type parameters.
It seems there is no documented/public way to access the internal SizeOfType
function used by the MemoryMappedViewAccessor
class, so the most practical way of getting the size of those structures would be to use reflection like this:
static readonly Func<Type, uint> SizeOfType = (Func<Type, uint>)Delegate.CreateDelegate(typeof(Func<Type, uint>), typeof(Marshal).GetMethod("SizeOfType", BindingFlags.NonPublic | BindingFlags.Static));
static void Write<T1, T2>(T1 item1, T2 item2)
where T1 : struct
where T2 : struct
{
using (MemoryMappedFile file = MemoryMappedFile.CreateNew(null, 32))
using (MemoryMappedViewAccessor accessor = file.CreateViewAccessor())
{
accessor.Write(0, ref item1);
accessor.Write(SizeOfType(typeof(T1)), ref item2);
}
}