Có không nhiều giải thích cho điều này, đây là những gì tôi có:Struct trong Struct, có khả năng thay đổi bên trong cấu trúc kiểu
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;
};
Về cơ bản tôi muốn các trường dữ liệu trong PACKET_DATA để có thể là một trong hai DATA_FILE hoặc DATA_MESSAGE. Tôi biết loại cần phải được thay đổi nhưng tôi không biết phải làm gì, là một lựa chọn generics?
kết quả cuối cùng nên để tôi có thể làm một trong hai:
pktData.data.fileName hoặc pktData.data.message
EDIT
tôi có thể làm:
public struct PACKET_DATA
{
public Command command;
public string data;
public DATA_MESSAGE data_message;
public DATA_FILE data_file;
};
và chỉ đặt data_message hoặc tệp thành rỗng khi tôi từng làm không cần chúng? điều này sẽ ảnh hưởng như thế nào đến mảng serial/byte và dữ liệu được gửi đi. Nếu tôi sử dụng các lớp học tôi sẽ không có cùng một vấn đề
EDIT 2
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;
};
Sửa 3
Tôi có một tiệt trùng và khử tiệt trùng làm việc với ví dụ ban đầu của tôi, nếu không có trục trặc với điều đó sau đó serialization thực tế được thực hiện.
EDIT 4
tất cả mọi thứ dường như được làm việc, ngoài một điều serializer của tôi là nhận được "cố gắng để đọc hay ghi bộ nhớ được bảo vệ. Đây thường là một dấu hiệu cho thấy bộ nhớ khác là tham nhũng." gunna có một cái nhìn vào nó khi bài giải pháp làm việc của tôi :)
EDIT 5
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 > 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;
}
CUỐI CÙNG
Các cấu trúc:
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<T>() 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;
}
Làm thế nào để tạo ra một mới Gói (probally có thể kết hợp với nhau tbh):
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;
}
(de) tuần tự hóa ở trên.
ví dụ đơn giản:
PACKET packet = Packet.CreatePacket(command, data_file);
byte[] byData = Packet.Serialize(packet);
đầu kia:
PACKET returnPacket = (PACKET)Packet.Deserialize(socketData.dataBuffer, typeof(PACKET));
// Get file
string fileName = returnPacket.pktData.GetData<DATA_FILE>().fileName;
long fileSize = returnPacket.pktData.GetData<DATA_FILE>().fileSize;
Tất cả dường như được làm việc tốt đẹp và dandy :)
chỉ cần làm rõ về EDIT của bạn: cấu trúc, là loại giá trị, không bao giờ là rỗng. Bạn sẽ cần một lá cờ cho biết thành viên nào là hợp lệ. –
các bạn chỉ nhận ra rằng chúng không thể rỗng. im nghĩ đến việc có 2 loại gói, xem ở trên, điều này có ý nghĩa hơn không? – Metalstorm
Ok, nhưng hãy nhớ rằng mã mà deserializes sẽ cần phải xác định loại. Tôi thực sự thích hai phiên bản cấu trúc con của bạn, bạn chỉ cần một 'bool isMessagePacket;'. –