Struct中的Struct,能够更改内部Struct类型

Met*_*orm 6 c# struct

对此没有太多解释,这就是我所拥有的:

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;       
    };
Run Code Online (Sandbox Code Playgroud)

基本上我希望PACKET_DATA中的数据字段能够是DATA_FILE或DATA_MESSAGE.我知道类型需要改变,但我不知道该怎么做,泛型是一种选择吗?

最终的结果应该是我可以做到:

pktData.data.fileName或pktData.data.message

编辑

我可以:

public struct PACKET_DATA
{
    public Command command;
    public string data;
    public DATA_MESSAGE data_message;
    public DATA_FILE data_file;
};
Run Code Online (Sandbox Code Playgroud)

并且只要我不需要它们就将data_message或文件设置为null?这将如何影响序列化/字节数组和正在发送的数据.如果我使用课程,我会遇到同样的问题

编辑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;
};
Run Code Online (Sandbox Code Playgroud)

编辑3

我有一个消毒器和消毒器,可以使用我的原始示例,如果没有打嗝,那么实际的序列化就完成了.

编辑4

除了我的序列化器正在尝试读取或写入受保护的内存之外,一切似乎都在起作用.这通常表明其他内存已损坏.在发布我的工作解决方案时,gunna看看它:)

编辑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;
    } 
Run Code Online (Sandbox Code Playgroud)

最后

结构:

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;
}
Run Code Online (Sandbox Code Playgroud)

如何创建一个新的数据包(概率可以结合在一起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;
    }
Run Code Online (Sandbox Code Playgroud)

(de)上面的序列化.

简单的例子:

PACKET packet = Packet.CreatePacket(command, data_file);
byte[] byData = Packet.Serialize(packet);
Run Code Online (Sandbox Code Playgroud)

另一端:

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;
Run Code Online (Sandbox Code Playgroud)

一切似乎工作得很好,花花公子:)

Che*_*hen 1

    public struct PACKET_DATA
    {
        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;
    }

PACKET_DATA packetData = new PACKET_DATA();
packetData.data = new DATA_MESSAGE();
var message = packetData.GetData<DATA_MESSAGE>().message;
Run Code Online (Sandbox Code Playgroud)