好吧,你可以有这样的地图:
private static readonlyDictionary<Type, Func<object, byte[]>> Converters =
new Dictionary<Type, Func<object, byte[]>>()
{
{ typeof(string), o => Encoding.UTF8.GetBytes((string) o) },
{ typeof(bool), o => BitConverter.GetBytes((bool) o) },
{ typeof(char), o => BitConverter.GetBytes((char) o) },
...
};
public static void ToBytes(object[] data, byte[] buffer)
{
int offset = 0;
foreach (object obj in data)
{
if (obj == null)
{
// Or do whatever you want
throw new ArgumentException("Unable to convert null values");
}
Func<object, byte[]> converter;
if (!Converters.TryGetValue(obj.GetType(), out converter))
{
throw new ArgumentException("No converter for " + obj.GetType());
}
byte[] obytes = converter(obj);
Buffer.BlockCopy(obytes, 0, buffer, offset, obytes.Length);
offset += obytes.Length;
}
}
您仍在为每种类型指定转换器,但它比 if/else 形式紧凑得多。
顺便说一句,还有其他各种构建字典的方法。你可以这样做:
private static readonly Dictionary<Type, Func<object, byte[]>> Converters =
new Dictionary<Type, Func<object, byte[]>>();
static WhateverYourTypeIsCalled()
{
AddConverter<string>(Encoding.UTF8.GetBytes);
AddConverter<bool>(BitConverter.GetBytes);
AddConverter<char>(BitConverter.GetBytes);
}
static void AddConverter<T>(Func<T, byte[]> converter)
{
Converters.Add(typeof(T), x => converter((T) x));
}
我看到另一个答案建议二进制序列化。我个人并不热衷于这样的“不透明”序列化方案。我想确切地知道数据中的内容,这意味着我可以将其移植到其他平台。
但是,我要指出,您当前的方案没有给出任何类型的分隔符 - 例如,如果您有两个字符串,您将不知道一个在哪里停止而另一个在哪里开始。您也不存储类型信息 - 这可能没问题,但可能不是。可变长度问题通常更为重要。您可以考虑使用长度前缀方案,例如BinaryWriter
. 实际上,BinaryWriter
一般来说,这很可能是一个更简单的解决方案。您可能仍然希望有一个代表地图,但让他们采取行动采取 aBinaryWriter
和价值。然后,您可以通过反射构建地图,或者只是一个硬编码的调用列表。
然后你只需初始化一个BinaryWriter
包装 a MemoryStream
,将每个值适当地写入它,然后调用ToArray
以MemoryStream
获取结果。