Convierta cualquier objeto en un byte

Estoy escribiendo un prototipo de conexión TCP y tengo problemas para homogeneizar los datos que se enviarán.

Por el momento, no estoy enviando más cadenas, pero en el futuro queremos poder enviar cualquier objeto.

El código es bastante simple en este momento, porque pensé que todo se podía convertir en una matriz de bytes:

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[]'. ... } 

Esto, por supuesto, se resuelve fácilmente con un

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

El problema es que, si lo hago de esa manera, necesito verificar CADA tipo de objeto que no se puede convertir en un byte [] en tiempo de ejecución.

Como no conozco todos los objetos que no se pueden convertir en un byte [] en tiempo de ejecución, esto realmente no es una opción.

¿Cómo se puede convertir un objeto en una matriz de bytes en C # .NET 4.0?

Usa el 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(); } } 

Tenga en cuenta que obj y cualquier propiedad / campo dentro de obj (y así sucesivamente para todas sus propiedades / campos) deberán etiquetarse con el atributo Serializable para ser serializados con éxito con esto.

consulte este artículo: http://www.morgantechspace.com/2013/08/convert-object-to-byte-array-and-vice.html

Usa el siguiente código

 // 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; } 

Como otros han dicho antes, podría usar la serialización binaria, pero puede producir bytes adicionales o deserializarse en objetos que no tienen exactamente los mismos datos. Usar la reflexión por otro lado es bastante complicado y muy lento. Hay otra solución que puede convertir estrictamente sus objetos a bytes y vise-versa – clasificación:

 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); 

Y para convertir bytes a un objeto:

 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); 

Es notablemente más lento y poco seguro utilizar este enfoque para objetos pequeños y estructuras en comparación con su propio campo de serialización por campo (debido a la doble copia desde / a la memoria no administrada), pero es la forma más fácil de convertir el objeto a byte [] sin implementar la serialización y sin el atributo [Serializable].

Lo que estás buscando es serialización. Hay varias formas de serialización disponibles para la plataforma .Net

  • Serialización binaria
  • Serialización XML: produce una cadena que se puede convertir fácilmente en un 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; } } 

Puedes usarlo como el siguiente código.

  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(); 

Puede usar las herramientas de serialización incorporadas en el marco y serializar a un MemoryStream . Esta puede ser la opción más sencilla, pero podría producir un byte más grande [] que el estrictamente necesario para su escenario.

Si ese es el caso, puede utilizar la reflexión para iterar sobre los campos y / o propiedades en el objeto a serializar y escribirlos manualmente en el MemoryStream, llamando a la serialización recursivamente si es necesario para serializar tipos no triviales. Este método es más complejo y tomará más tiempo implementarlo, pero le permite un mayor control sobre la transmisión serializada.

Manera alternativa de convertir el objeto a matriz de bytes:

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

Clase combinada de soluciones en extensiones:

 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 string Serialize(this object obj) { return JsonConvert.SerializeObject(obj); } } 

¿Qué hay de la serialización? échale un vistazo aquí .

Prefiero usar la expresión “serialización” que “conversión en bytes”. Serializar un objeto significa convertirlo en una matriz de bytes (o XML, u otra cosa) que se puede usar en el cuadro remoto para reconstruir el objeto. En .NET, el atributo Serializable marca los tipos cuyos objetos se pueden serializar.

Saludos, Matthias

Una implementación adicional, que utiliza el JSON binario de Newtonsoft.Json y no requiere marcar todo con el atributo [Serializable]. Solo un inconveniente es que un objeto debe estar envuelto en una clase anónima, por lo que el conjunto de bytes obtenido con la serialización binaria puede ser diferente de este.

 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(); } } } 

Se usa una clase anónima porque BSON debería comenzar con una clase o matriz. No he intentado deserializar byte [] de nuevo a objeto y no estoy seguro si funciona, pero he probado la velocidad de conversión a byte [] y satisface completamente mis necesidades.

¿Qué tal algo tan simple como esto?

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