2

There have been variants on this question, but the ones I found were "I have a struct in a C DLL". In this case, I have 100% C# code. I have a struct that contains a variable length array of structs that I am trying to marshal to a tightly packed byte array. I'm using structs and Marshal.StructureToPtr because I need a tightly packed array without all of the metadata that BinaryReader/Writer use to help it serialize and deserialize.

Here is the struct definition:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct CharacterSelect_Struct
{
    public uint CharCount;
    public uint TotalChars;

    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct)]
    public CharacterSelectEntry_Struct[] Entries;

    public static CharacterSelect_Struct Initialize(uint totalChars, uint charCount)
    {
        return new CharacterSelect_Struct
        {
            CharCount = charCount,
            TotalChars = totalChars,
            Entries = 0 != charCount ? new CharacterSelectEntry_Struct[charCount] : null
        };
    }
}

This works great if Entries contains 1 element. If it contains 2 or more I still only ever get the contents of the first element.

Is there a way to serialize the above and get all of the contents of Entries, or do I have to manually serialize the above, and if so, other than doing, "Serialize each Entry separately and append to a list, then serialize the outer struct"?

I went with a struct and Marshal.StructureToPtr approach because it seemed easier than going with classes and manually writing all of the serialization and deserialization using BitConverter, but I'm wondering if there's a simpler way to give me what I need..

M. Biolic
  • 193
  • 1
  • 1
  • 5
  • 1
    Or you could not use any serialization at all and simply write classes/structs to abstract over the array directly (by being nothing more than an index into it). As a bonus, this would almost certainly be faster than copying data back and forth. Note that as written, a struct containing an array of structs is usually [a bad idea](http://stackoverflow.com/questions/441309/). – Jeroen Mostert Oct 10 '16 at 13:22
  • I'm not sure I'm following. So I would have a byte array contained in the struct (or class at that point) with properties that get and set data directly from/to the byte array? That seems fairly error prone to manage properly and would result in a lot of allocations whenever I had to grow the backing byte array? If I'm misunderstanding, please elaborate because I'm curious to hear your thoughts. – M. Biolic Oct 10 '16 at 13:52
  • 1
    Well, you could use a `List` rather than an array if you want dynamic allocation, but yes, that's the idea. This is useful if memory is tight and you *always* want the data to be tightly packed. If you only *sometimes* want to serialize the data, this would not be the right approach (but then neither is using `Marshal`, really -- it's hardly "easier" if you first need to understand how marshalling works, exactly, as in the case of variable-length arrays in structs, which cannot be done with a single call). I'd prefer writing out the serialization code myself. – Jeroen Mostert Oct 10 '16 at 15:19
  • @JeroenMostert - If you want to make your comment an official answer I'll upvote it. I took your advice and have a new approach that appears to work in isolation. Writing tests and it's extremely performant. Went with a cached fieldinfo route using reflection that saves me the maintenance headaches of hardcoding the serialization / deserialization rules, works with classes, and lets me remove all of the marshaling bits. – M. Biolic Oct 14 '16 at 12:37
  • 1
    It sounds like you put in a lot more useful work than I did. :-) Feel free to answer your own question with some sordid details, this is much more useful to future readers than my off-the-cuff advice. – Jeroen Mostert Oct 14 '16 at 13:44

0 Answers0