Convertir n’importe quel object en un octet

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 dans le futur, nous voulons pouvoir envoyer n’importe quel object.

Le code est assez simple pour le moment, car je pensais que tout pouvait être converti en un tableau d’octets:

void SendData(object headerObject, object bodyObject) { byte[] header = (byte[])headerObject; //ssortingngs at runtime, byte[] body = (byte[])bodyObject; //invalid cast exception // Unable to cast object of type 'System.Ssortingng' to type 'System.Byte[]'. ... } 

Ceci est bien sûr assez facilement résolu avec un

 if( state.headerObject is System.Ssortingng ){...} 

Le problème est que, si je le fais de cette façon, je dois rechercher TOUS les types d’objects qui ne peuvent pas être convertis en octets [] lors de l’exécution.

Comme je ne connais pas tous les objects qui ne peuvent pas être convertis en octet [] lors de l’exécution, ce n’est vraiment pas une option.

Comment peut-on convertir un object dans un tableau d’octets dans C # .NET 4.0?

Utilisez le BinaryFormatter :

 byte[] ObjectToByteArray(object obj) { if(obj == null) return null; BinaryFormatter bf = new BinaryFormatter(); using (MemoryStream ms = new MemoryStream()) { bf.Serialize(ms, obj); return ms.ToArray(); } } 

Notez que obj et toutes les propriétés / champs dans obj (et ainsi de suite pour toutes leurs propriétés / champs) devront tous être marqués avec l’ atsortingbut Serializable pour être sérialisés avec succès avec cela.

consultez cet article: http://www.morgantechspace.com/2013/08/convert-object-to-byte-array-and-vice.html

Utilisez le code ci-dessous

 // Convert an object to a byte array private byte[] ObjectToByteArray(Object obj) { if(obj == null) return null; BinaryFormatter bf = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); bf.Serialize(ms, obj); return ms.ToArray(); } // Convert a byte array to an Object private Object ByteArrayToObject(byte[] arrBytes) { MemoryStream memStream = new MemoryStream(); BinaryFormatter binForm = new BinaryFormatter(); memStream.Write(arrBytes, 0, arrBytes.Length); memStream.Seek(0, SeekOrigin.Begin); Object obj = (Object) binForm.Deserialize(memStream); return obj; } 

Comme d’autres l’ont déjà dit, vous pouvez utiliser la sérialisation binary, mais elle peut produire des octets supplémentaires ou être désérialisée en des objects n’ayant pas exactement les mêmes données. L’utilisation de la reflection est en revanche assez compliquée et très lente. Il existe une autre solution qui peut convertir ssortingctement vos objects en octets et vice-versa:

 var size = Marshal.SizeOf(your_object); // Both managed and unmanaged buffers required. var bytes = new byte[size]; var ptr = Marshal.AllocHGlobal(size); // Copy object byte-to-byte to unmanaged memory. Marshal.StructureToPtr(your_object, ptr, false); // Copy data from unmanaged memory to managed buffer. Marshal.Copy(ptr, bytes, 0, size); // Release unmanaged memory. Marshal.FreeHGlobal(ptr); 

Et pour convertir des octets en object:

 var bytes = new byte[size]; var ptr = Marshal.AllocHGlobal(size); Marshal.Copy(bytes, 0, ptr, size); var your_object = (YourType)Marshal.PtrToStructure(ptr, typeof(YourType)); Marshal.FreeHGlobal(ptr); 

Il est nettement plus lent et peu sûr d’utiliser cette approche pour les petits objects et les structures en comparant à votre propre champ de sérialisation par champ (à cause de la double copie depuis / vers la mémoire non managée). et sans atsortingbut [Serializable].

Ce que vous recherchez, c’est la sérialisation. Il existe plusieurs formes de sérialisation disponibles pour la plate-forme .Net

  • Sérialisation Binaire
  • Sérialisation XML: produit une chaîne facilement convertible en byte[]
  • ProtoBuffers
 public static class SerializerDeserializerExtensions { public static byte[] Serializer(this object _object) { byte[] bytes; using (var _MemoryStream = new MemoryStream()) { IFormatter _BinaryFormatter = new BinaryFormatter(); _BinaryFormatter.Serialize(_MemoryStream, _object); bytes = _MemoryStream.ToArray(); } return bytes; } public static T Deserializer(this byte[] _byteArray) { T ReturnValue; using (var _MemoryStream = new MemoryStream(_byteArray)) { IFormatter _BinaryFormatter = new BinaryFormatter(); ReturnValue = (T)_BinaryFormatter.Deserialize(_MemoryStream); } return ReturnValue; } } 

Vous pouvez l’utiliser comme ci-dessous le code.

  DataTable _DataTable = new DataTable(); _DataTable.Columns.Add(new DataColumn("Col1")); _DataTable.Columns.Add(new DataColumn("Col2")); _DataTable.Columns.Add(new DataColumn("Col3")); for (int i = 0; i < 10; i++) { DataRow _DataRow = _DataTable.NewRow(); _DataRow["Col1"] = (i + 1) + "Column 1"; _DataRow["Col2"] = (i + 1) + "Column 2"; _DataRow["Col3"] = (i + 1) + "Column 3"; _DataTable.Rows.Add(_DataRow); } byte[] ByteArrayTest = _DataTable.Serializer(); DataTable dt = ByteArrayTest.Deserializer(); 

Vous pouvez utiliser les outils de sérialisation intégrés dans le framework et les sérialiser à un MemoryStream . Cela peut être l’option la plus simple, mais peut produire un octet plus grand [] que ce qui peut être ssortingctement nécessaire pour votre scénario.

Si tel est le cas, vous pouvez utiliser la reflection pour parcourir les champs et / ou les propriétés de l’object à sérialiser et les écrire manuellement dans MemoryStream, en appelant la sérialisation de manière récursive si nécessaire pour sérialiser des types non sortingviaux. Cette méthode est plus complexe et prend plus de temps à implémenter, mais vous permet de contrôler davantage le stream sérialisé.

Autre moyen de convertir un object en tableau d’octets:

  TypeConverter objConverter = TypeDescriptor.GetConverter(objMsg.GetType()); byte[] data = (byte[])objConverter.ConvertTo(objMsg, typeof(byte[])); 

Combined Solutions in Extensions:

 public static class Extensions { public static byte[] ToByteArray(this object obj) { var size = Marshal.SizeOf(data); var bytes = new byte[size]; var ptr = Marshal.AllocHGlobal(size); Marshal.StructureToPtr(data, ptr, false); Marshal.Copy(ptr, bytes, 0, size); Marshal.FreeHGlobal(ptr); return bytes; } public static ssortingng Serialize(this object obj) { return JsonConvert.SerializeObject(obj); } } 

Qu’en est-il de la sérialisation? jetez un oeil ici .

Je préfère utiliser l’expression “sérialisation” que “lancer en octets”. Sérialiser un object signifie le convertir en un tableau d’octets (ou XML, ou autre) pouvant être utilisé sur la boîte distante pour reconstruire l’object. Dans .NET, l’ atsortingbut Serializable marque les types dont les objects peuvent être sérialisés.

Cheers, Matthias

Une implémentation supplémentaire, qui utilise le JSON binary Newtonsoft.Json et ne nécessite pas de tout marquer avec l’atsortingbut [Serializable]. Un seul inconvénient est qu’un object doit être encapsulé dans une classe anonyme, de sorte que le tableau d’octets obtenu avec la sérialisation binary peut être différent de celui-ci.

 public static byte[] ConvertToBytes(object obj) { using (var ms = new MemoryStream()) { using (var writer = new BsonWriter(ms)) { var serializer = new JsonSerializer(); serializer.Serialize(writer, new { Value = obj }); return ms.ToArray(); } } } 

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 les octets [] pour les objecter et je ne sais pas si cela fonctionne, mais j’ai testé la vitesse de conversion en octets [] et cela répond complètement à mes besoins.

Que diriez-vous de quelque chose de simple comme ça?

 return ((object[])value).Cast().ToArray();