J'écris un prototype de connexion TCP et j'ai du mal à homogénéiser les données à envoyer.
Pour le moment, je n'envoie que des chaînes, mais à l'avenir nous voulons pouvoir envoyer n'importe quel objet.
Le code est assez simple pour le moment, car je pensais que tout pouvait être converti dans un tableau d'octets:
void SendData(object headerObject, object bodyObject)
{
byte[] header = (byte[])headerObject; //strings at runtime,
byte[] body = (byte[])bodyObject; //invalid cast exception
// Unable to cast object of type 'System.String' to type 'System.Byte[]'.
...
}
Ceci est bien sûr assez facilement résolu avec un
if( state.headerObject is System.String ){...}
Le problème est que si je le fais de cette façon, je dois vérifier CHAQUE type d'objet qui ne peut pas être converti en octet [] lors de l'exécution.
Puisque je ne connais pas tous les objets qui ne peuvent pas être convertis en octet [] à l'exécution, ce n'est vraiment pas une option.
Comment convertir n'importe quel objet en un tableau d'octets en C # .NET 4.0?
FileStream
, ou tout objet qui encapsule un handle comme celui-ci).Réponses:
Utilisez le
BinaryFormatter
:Notez que
obj
toutes les propriétés / champs dansobj
(et ainsi de suite pour toutes leurs propriétés / champs) devront tous être étiquetés avec l'Serializable
attribut pour être sérialisés avec cela.la source
using
bloc, car il libèrera avec empressement le tampon interne utilisé.consultez cet article: http://www.morgantechspace.com/2013/08/convert-object-to-byte-array-and-vice.html
Utilisez le code ci-dessous
la source
MemorySteam
doit être enveloppé dans unusing
bloc.Comme d'autres l'ont déjà dit, vous pouvez utiliser la sérialisation binaire, mais cela peut produire des octets supplémentaires ou être désérialisé en objets avec pas exactement les mêmes données. Utiliser la réflexion par contre est assez compliqué et très lent. Il existe une autre solution qui permet de convertir strictement vos objets en octets et vice-versa - le marshalling:
Et pour convertir des octets en objet:
Il est nettement plus lent et en partie dangereux d'utiliser cette approche pour les petits objets et structures par rapport à votre propre champ de sérialisation par champ (en raison de la double copie de / vers la mémoire non gérée), mais c'est le moyen le plus simple de convertir strictement l'objet en octet [] sans implémenter la sérialisation et sans attribut [Serializable].
la source
StructureToPtr
+Copy
est lent? Comment peut-il être plus lent que la sérialisation? Existe-t-il une solution plus rapide?var bytes = new byte[size];
Ce que vous recherchez, c'est la sérialisation. Il existe plusieurs formes de sérialisation disponibles pour la plateforme .Net
byte[]
la source
Vous pouvez l'utiliser comme le code ci-dessous.
la source
L'utilisation
Encoding.UTF8.GetBytes
est plus rapide que l'utilisationMemoryStream
. Ici, j'utilise NewtonsoftJson pour convertir l'objet d'entrée en chaîne JSON, puis j'obtiens les octets de la chaîne JSON.Benchmark pour la version de @Daniel DiPaolo avec cette version
la source
Solutions combinées dans la classe Extensions:
la source
Vous pouvez utiliser les outils de sérialisation intégrés dans le framework et sérialiser vers un MemoryStream . Cela peut être l'option la plus simple, mais peut produire un octet [] plus grand que ce qui peut être strictement nécessaire pour votre scénario.
Si tel est le cas, vous pouvez utiliser la réflexion pour parcourir les champs et / ou propriétés de l'objet à sérialiser et les écrire manuellement dans le MemoryStream, en appelant la sérialisation de manière récursive si nécessaire pour sérialiser des types non triviaux. Cette méthode est plus complexe et prendra plus de temps à implémenter, mais vous permet de mieux contrôler le flux sérialisé.
la source
Que diriez-vous de quelque chose de simple comme ça?
la source
Je préfère utiliser l'expression «sérialisation» plutôt que «transtypage en octets». Sérialiser un objet signifie le convertir en un tableau d'octets (ou XML, ou autre chose) qui peut être utilisé sur la boîte distante pour reconstruire l'objet. Dans .NET, l'
Serializable
attribut marque les types dont les objets peuvent être sérialisés.la source
Autre façon de convertir un objet en tableau d'octets:
la source
Une implémentation supplémentaire, qui utilise le JSON binaire Newtonsoft.Json et ne nécessite pas de tout marquer avec l'attribut [Serializable]. Un seul inconvénient est qu'un objet doit être enveloppé dans une classe anonyme, donc le tableau d'octets obtenu avec la sérialisation binaire peut être différent de celui-ci.
La classe anonyme est utilisée car BSON doit commencer par une classe ou un tableau. Je n'ai pas essayé de désérialiser l'octet [] en objet et je ne suis pas sûr que cela fonctionne, mais j'ai testé la vitesse de conversion en octet [] et cela satisfait complètement mes besoins.
la source
Et la sérialisation? jetez un oeil ici .
la source