好了,你可以有一個圖是這樣的:
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
和價值。然後,您可以通過反射來構建地圖,或者只是一個硬編碼的調用列表。
然後,您只需初始化一個包裝MemoryStream
的BinaryWriter
,將每個值適當寫入它,然後撥MemoryStream
上的ToArray
即可獲得結果。
更重要的是,目前的方案不提供任何類型的信息。例如,您不知道您讀回的是「整數」還是「浮點數」。 – 2009-09-06 15:04:58
@Mehrdad:這可能是一個問題,但它可能不是。類型信息*可以隱含 - 例如對象可以是類型中字段的值,其中整體類型是事先已知的。 – 2009-09-06 15:06:52
謝謝你的答案。我知道變長問題,但試圖限制這個問題。我一直在使用的解決方案是將每個對象的長度存儲爲一個單獨的字節數組,並將其轉換後的數據複製到緩衝區。類型信息對於客戶端和服務器都是已知的,所以這不是問題。 您的解決方案看起來不錯,因爲服務器需要能夠與.NET客戶端和Java客戶端通信。 – remdao 2009-09-06 16:00:39