这是我到目前为止所提出的,但对于更好的方法,它似乎不是最优的,是什么想法?
public void ToBytes(object[] data, byte[] buffer)
{
byte[] obytes;
int offset = 0;
foreach (object obj in data)
{
if (obj is string)
obytes = System.Text.Encoding.UTF8.GetBytes(((string)obj));
else if (obj is bool)
obytes = BitConverter.GetBytes((bool)obj);
else if (obj is char)
obytes = BitConverter.GetBytes((char)obj);
// And so on for each valuetype
Buffer.BlockCopy(obytes, 0, buffer, offset, obytes.Length);
offset += obytes.Length;
}
}
答案 0 :(得分:4)
嗯,你可以有这样的地图:
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
一般来说可能是一个更简单的解决方案。您可能希望仍然拥有代理地图,但要让它们采取BinaryWriter
和值的操作。然后,您可以通过反射构建地图,或者仅使用硬编码的调用列表。
然后,您只需初始化BinaryWriter
包裹MemoryStream
,将每个值适当地写入其中,然后在ToArray
上调用MemoryStream
以获得结果。< / p>
答案 1 :(得分:2)
您可能应该考虑使用BinaryFormatter
代替:
var formatter = new BinaryFormatter();
var stream = new MemoryStream();
formatter.Serialize(stream, obj);
byte[] result = stream.ToArray();
除此之外,还有一些非常好的序列化框架,如Google Protocol Buffers,如果你想避免重新发明轮子。
答案 2 :(得分:0)
您可以使用StreamWriter写入内存流并使用其缓冲区:
{
byte[] result;
using (MemoryStream stream = new MemoryStream())
{
StreamWriter writer = new StreamWriter(stream);
writer.WriteLine("test");
writer.WriteLine(12);
writer.WriteLine(true);
writer.Flush();
result = stream.GetBuffer();
}
using(MemoryStream stream=new MemoryStream(result))
{
StreamReader reader = new StreamReader(stream);
while(! reader.EndOfStream)
Console.WriteLine(reader.ReadLine());
}
}