我有一个byte [],其中前两个字节是ushort,它提供一个ID,该ID告诉我数组其余部分包含的数据类型。基于此ID,我需要创建一个具有正确类型的结构以填充接收到的数据。
现在我以为我可能可以使用Dictionary,在启动时填充它,然后通过它获得正确的类型,但这会涉及很多反射和装箱,因为我要处理很多byte []。
有没有可能的解决方法,无需装箱和反射即可根据ushort ID创建所需的structtype?
编辑:
public struct TestMessage
{
public const ushort typeCode = (ushort)Enums.MessageOpcodes.TestMessage;
public uint testuInt { internal set; get; }
public ushort testuShort { internal set; get; }
public ulong testuLong { internal set; get; }
public TestMessage(uint uInt, ushort uShort, ulong uLong)
{
testuInt = uInt;
testuShort = uShort;
testuLong = uLong;
}
}
public static ReadOnlyDictionary<ushort, object> messageTypes;
private static void PopulateMessageDict()
{
var tempMessageTypes = new Dictionary<ushort, object>();
tempMessageTypes.TryAdd(TestMessage.typeCode, new TestMessage());
messageTypes = new ReadOnlyDictionary<ushort, object>(tempMessageTypes);
}
public void TryAdd(this Dictionary<ushort, object> dictionary, ushort key, object value)
{
if (!dictionary.ContainsKey(key))
{
dictionary.Add(key, value);
}
else
{
Debug.Log("Key already exists in dictionary.");
}
}
答案 0 :(得分:0)
因此,根据您的评论,我认为您根本不需要字典。
您说过要占用一些字节,查看前两个以确定消息类型,然后反序列化为正确类型的消息,然后以特定于该类型的方式对其进行处理。
因此,从高度上讲,您想要的是:
var opCode = (Enums.MessageOpcodes)(data[0] << 8 | data[1]);
switch (opCode)
{
case Enums.MessageOpcodes.TestMessage:
ProcessTestMessage(data);
break;
case Enums.MessageOpcodes.VectorMessage:
ProcessVectorMessage(data);
break;
}
然后,您的ProcessTestMessage
方法反序列化为TestMessage
结构,然后对其进行处理;同样,您的ProcessVectorMessage
和VectorMessage
结构。
您可以概括一下:
interface IMessageProcessor
{
Enums.MessageOpcodes Opcode { get; }
void DeserializeAndProcess(byte[] data);
}
然后:
class TestMessageProcessor : IMessageProcessor
{
public Enums.MessageOpcodes Opcode => Enums.MessageOpcodes.TestMessage;
public void DeserializeAndProcess(byte[] data)
{
// Deserialize into a TestMessage
// Process
}
}
然后您就拥有了Dictionary<Enums.MessageOpcodes, IMessageProcessor>
(或者由于密钥是IMessageProcessor
的属性,您可以使用KeyedCollection
):
class MessageProcessorLookup : KeyedCollection<Enums.MessageOpcodes, IMessageProcessor>
{
public override Enums.MessageOpcodes GetKeyForItem(IMessageProcessor item) => item.Opcode;
}
然后:
var lookup = new MessageProcessorLookup() { new TestMessageProcessor(), .... };
...
lookup[opcode].DeserializeAndProcess(data);
最终,如果您有一堆不同的结构,而又不想将它们装箱,则不能的代码表明“将数据反序列化为合适的结构-我不知道”不在乎是什么-然后将其还给我”,因为您将不得不将结构装箱以将其还给我。同样,您不能说“将数据反序列化为适当的结构,然后将其推送到处理所有消息类型的ConcurrentQueue上”,而无需装箱。所有处理都必须是“仅向前”的,使用反序列化为struct的方法,然后调用处理它的方法。