Eh bien, vous pourriez avoir une carte comme celle-ci:
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;
}
}
vous spécifiez toujours le convertisseur pour chaque type, mais il est beaucoup plus compact que le si/forme d'autre.
Il existe plusieurs autres façons de construire le dictionnaire, btw. Vous pouvez le faire comme ceci:
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));
}
Je vois une autre réponse a suggéré sérialisation binaire. Personnellement, je ne suis pas intéressé par les schémas de sérialisation "opaques" comme ça. J'aime savoir exactement ce qui se passera dans les données de telle sorte que je puisse le porter sur d'autres plateformes.
Je voudrais souligner, cependant, que votre schéma actuel ne donne aucune sorte de délimiteur - si vous avez deux chaînes, vous n'auriez aucune idée où l'un s'est arrêté et l'autre a commencé, par exemple. Vous ne stockez pas non plus les informations de type - cela peut être correct, mais ce n'est peut-être pas le cas. La question de la longueur variable est généralement plus importante. Vous pouvez envisager d'utiliser un schéma de longueur-préfixe, comme celui de BinaryWriter
. En effet, BinaryWriter
pourrait bien être une solution plus simple en général. Vous voudrez probablement toujours avoir une carte des délégués, mais faites-leur des actions en prenant un BinaryWriter
et une valeur. Vous pourriez ensuite construire la carte par réflexion, ou simplement une liste d'appels codés en dur.
alors vous simplement initialiser un BinaryWriter
enroulant un MemoryStream
, écrire chaque valeur de manière appropriée, puis appelez ToArray
sur le MemoryStream
pour obtenir les résultats.
Plus important encore, le schéma actuel ne fournit aucun type d'information de type. Vous n'aurez aucune idée si ce que vous lisez est un 'integer' ou un' float', par exemple. –
@Mehrdad: Cela peut être un problème, mais ce n'est peut-être pas le cas. L'information de type * peut être implicite - par ex. les objets peuvent être les valeurs des champs d'un type, où le type global est connu à l'avance. –
Merci pour vos réponses. Je connais le problème de la longueur variable, mais j'ai essayé de limiter la question. La solution que j'ai utilisée pour cela est de stocker la longueur de chaque objet en tant que shorts dans un tableau d'octets séparé qui après la conversion copié dans le tampon. Les informations de type sont connues à la fois par le client et le serveur, ce qui ne pose aucun problème. Votre solution semble intéressante car le serveur doit pouvoir communiquer avec un client .NET et un client Java. – remdao