title: Struct within Struct, able to change inner Struct type
body: <p>There isn't much explaining to this, this is what I have:</p>
  
  <pre><code>public struct PACKET_HEADER
      {
          public string computerIp;
          public string computerName;
          public string computerCustomName;
      };
  
      public struct PACKET
      {
          public PACKET_HEADER pktHdr;
          public PACKET_DATA pktData;
      };
  
  
      public struct PACKET_DATA
      {
          public Command command;
          public string data;  
      };
  
      public struct DATA_MESSAGE
      {
          public string message;
      };
  
      public struct DATA_FILE
      {
          public string fileName;
          public long fileSize;       
      };
  </code></pre>
  
  <p>Basically I want the data field in PACKET_DATA to be able to be either DATA_FILE or DATA_MESSAGE. I know the type needs to be changed but I don't know what to, is generics an option?</p>
  
  <p>the end result should be so that I can do either:</p>
  
  <p>pktData.data.fileName
  or
  pktData.data.message </p>
  
  <p><strong>EDIT</strong></p>
  
  <p>i could do:</p>
  
  <pre><code>public struct PACKET_DATA
  {
      public Command command;
      public string data;
      public DATA_MESSAGE data_message;
      public DATA_FILE data_file;
  };
  </code></pre>
  
  <p>and just set the data_message or file to null when ever i don't need them? how would this impact the serialization / byte array and the data being sent. If I used classes would I not have the same problem</p>
  
  <p><strong>EDIT 2</strong></p>
  
  <pre><code>public struct PACKET_MESSAGE
  {
      public PACKET_HEADER pktHdr;
      public Command command;
      public DATA_MESSAGE pktData;
  };
  
  public struct PACKET_FILE
  {
      public PACKET_HEADER pktHdr;
      public Command command;
      public DATA_FILE pktData;
  };
  </code></pre>
  
  <p><strong>Edit 3</strong></p>
  
  <p>I have a sterilizer and de-sterilizer that works with my original example, if there are no hiccups with that then the actual serialization is done.</p>
  
  <p><strong>EDIT 4</strong></p>
  
  <p>everything seems to be working, apart from one things my serializer is getting "Attempted to read or write protected memory. This is often an indication that other memory is corrupt." gunna have a look at it when post my working solution :)</p>
  
  <p><strong>EDIT 5</strong></p>
  
  <pre><code>    public static byte[] Serialize(object anything)
      {
          int rawsize = Marshal.SizeOf(anything);
          byte[] rawdatas = new byte[rawsize];
          GCHandle handle = GCHandle.Alloc(rawdatas, GCHandleType.Pinned);
          IntPtr buffer = handle.AddrOfPinnedObject();
          Marshal.StructureToPtr(anything, buffer, false);
          handle.Free();
          return rawdatas;
      }
  
      public static object Deserialize(byte[] rawdatas, Type anytype)
      {
          int rawsize = Marshal.SizeOf(anytype);
          if (rawsize &gt; rawdatas.Length)
              return null;
          GCHandle handle = GCHandle.Alloc(rawdatas, GCHandleType.Pinned);
          IntPtr buffer = handle.AddrOfPinnedObject();
          object retobj = Marshal.PtrToStructure(buffer, anytype);
          handle.Free();
          return retobj;
      } 
  </code></pre>
  
  <p><strong>FINAL</strong></p>
  
  <p>The structs:</p>
  
  <pre><code>public struct PACKET_HEADER
  {
      public string computerIp;
      public string computerName;
      public string computerCustomName;
  };
  
  public struct PACKET
  {
      public PACKET_HEADER pktHdr;
      public PACKET_DATA pktData;
  };
  
  public struct PACKET_DATA
  {
      public Command command;
      public IDATA data;
      public T GetData&lt;T&gt;() where T : IDATA
      {
          return (T)(data);
      }
  }
  
  public interface IDATA { }
  
  public struct DATA_MESSAGE : IDATA
  {
      public string message;
  }
  
  public struct DATA_FILE : IDATA
  {
      public string fileName;
      public long fileSize;
  }
  </code></pre>
  
  <p>How to create a new Packet (probally could combine together tbh):</p>
  
  <pre><code>    public static PACKET CreatePacket(Command command)
      {
          PACKET packet;
          packet.pktHdr.computerIp = Settings.ComputerIP;
          packet.pktHdr.computerName = Settings.ComputerName;
          packet.pktHdr.computerCustomName = Settings.ComputerCustomName;
  
          packet.pktData.command = command;
          packet.pktData.data = null;
  
          return packet;
      }
  
      public static PACKET CreatePacket(Command command, DATA_MESSAGE data_message)
      {
          PACKET packet;
          packet.pktHdr.computerIp = Settings.ComputerIP;
          packet.pktHdr.computerName = Settings.ComputerName;
          packet.pktHdr.computerCustomName = Settings.ComputerCustomName;
  
          packet.pktData.command = command;
          packet.pktData.data = data_message;
  
          return packet;
      }
  
      public static PACKET CreatePacket(Command command, DATA_FILE data_file)
      {
          PACKET packet;
          packet.pktHdr.computerIp = Settings.ComputerIP;
          packet.pktHdr.computerName = Settings.ComputerName;
          packet.pktHdr.computerCustomName = Settings.ComputerCustomName;
  
          packet.pktData.command = command;
          packet.pktData.data = data_file;
  
          return packet;
      }
  </code></pre>
  
  <p>(de) serialization above.</p>
  
  <p>Simple example:</p>
  
  <pre><code>PACKET packet = Packet.CreatePacket(command, data_file);
  byte[] byData = Packet.Serialize(packet);
  </code></pre>
  
  <p>other end:</p>
  
  <pre><code>PACKET returnPacket = (PACKET)Packet.Deserialize(socketData.dataBuffer, typeof(PACKET));
                          // Get file
  string fileName = returnPacket.pktData.GetData&lt;DATA_FILE&gt;().fileName;
  long fileSize = returnPacket.pktData.GetData&lt;DATA_FILE&gt;().fileSize;
  </code></pre>
  
  <p>All seems to be working  nice and dandy :)</p>