さて、あなたはこのような地図を持つことができます:
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));
}
別の答えがバイナリシリアル化を示唆しているのがわかります。私は個人的に、そのような「不透明な」シリアル化スキームには熱心ではありません。他のプラットフォームに移植できるという意味で、データに何が含まれるのかを正確に知りたいです。
ただし、現在のスキームでは区切り文字が指定されていないことを指摘しておきます。たとえば、2つの文字列がある場合、一方が停止し、もう一方が開始した場所がわかりません。また、タイプ情報を保存しません-それは問題ないかもしれませんが、そうではないかもしれません。通常、可変長の問題の方が重要です。のような長さプレフィックススキームの使用を検討することもできますBinaryWriter
。確かに、BinaryWriter
一般的にはもっと簡単な解決策かもしれません。デリゲートのマップを引き続き作成したい場合は、デリゲートにBinaryWriter
と値をとるアクションを作成します。次に、リフレクション、またはハードコードされた呼び出しのリストによってマップを作成できます。
次に、BinaryWriter
ラッピングを初期化し、MemoryStream
各値を適切に書き込んでから、を呼び出しToArray
てMemoryStream
結果を取得します。