Convertir n'importe quel objet à un byte[]
Je suis en train d'écrire un prototype de connexion TCP et je vais avoir quelques difficultés à homogénéiser les données à envoyer.
En ce moment, je suis l'envoi de rien, mais les cordes, mais dans l'avenir, nous voulons être en mesure d'envoyer n'importe quel objet.
Le code est assez simple pour le moment, parce que je pensais que tout ce qui pourrait être jeté 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[]'.
...
}
Bien sûr, cela se trouve 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, j'ai besoin de vérifier, pour CHAQUE type d'objet qui ne peut pas être lancée à un byte[] au moment de l'exécution.
Depuis je ne sais pas tous les objets qui ne peuvent pas être jeté dans un byte[] au moment de l'exécution, ce n'est vraiment pas une option.
Comment convertir n'importe quel objet dans un tableau d'octets en C# .NET 4.0?
- Ce n'est pas possible de manière significative, en général (prenons, par exemple, une instance de
FileStream
, ou n'importe quel objet qui encapsule une poignée comme ça). - Avez-vous l'intention d'avoir tous les clients en cours d'exécution .NET? Si la réponse est non, vous devriez envisager une autre forme de sérialisation (XML, JSON, ou les goûts)
Vous devez vous connecter pour publier un commentaire.
Utiliser le
BinaryFormatter
:Noter que
obj
et les propriétés des champs dansobj
(et donc-pour l'ensemble de leurs propriétés, des champs) devront tous être marqués avec leSerializable
l'attribut pour réussir à être sérialisé avec cette.using
bloc, qu'il s'empressera de libération de la mémoire tampon interne utilisé.checkout cet article :http://www.morgantechspace.com/2013/08/convert-object-to-byte-array-and-vice.html
Utiliser le code ci-dessous
MemorySteam
doit être enveloppé dans unusing
bloc.Comme d'autres l'ont dit avant, vous pouvez utiliser la sérialisation binaire, mais elle peut produire une octets supplémentaires ou être désérialisée dans un des objets ayant pas exactement les mêmes données. L'utilisation de la réflexion sur l'autre main est assez compliqué et très lent.
Il y a une autre solution qui peut strictement convertir vos objets d'octets et vice-versa - ordonnancement:
Et de convertir des octets de l'objet:
C'est nettement plus lent et en partie impropre à l'utilisation de cette approche pour les petits objets et les structures de comparer à votre propre sérialisation champ par champ (à cause du double de la copie de/vers la mémoire non gérée), mais il est facile d'strictement convertit l'objet en byte[] sans la mise en œuvre de la sérialisation et sans attribut [Serializable].
StructureToPtr
+Copy
est lent? Comment peut-il être plus lente que la sérialisation? Est-il une solution plus rapide?var bytes = new byte[size];
Marshal.SizeOf()
jeter l'exception:"Type '' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed."
var size = Marshal.SizeOf(typeof(YourType));
, je pensais que cela devrait être évident. Et oui, bien sûr, de votre type doit prendre en charge la sérialisation. Vous pouvez le faire avec les attributs: stackoverflow.com/questions/1345178/...Ce que vous cherchez est la sérialisation. Il existe plusieurs formes de sérialisation disponible pour le .Net plate-forme
byte[]
Vous pouvez l'utiliser comme code ci-dessous.
Des Solutions combinées dans les Extensions de classe:
À l'aide de
Encoding.UTF8.GetBytes
est plus rapide que l'utilisationMemoryStram
.Ici, je suis en utilisant NewtonsoftJson pour convertir les données d'entrée de l'objet à chaîne JSON et l'obtention d'octets à partir de chaîne JSON.
De référence pour @Daniel DiPaolo version avec cette version
Vous pouvez utiliser le construit-dans la sérialisation des outils dans le cadre et à la sérialisation d'un MemoryStream. Cela peut être l'option la plus simple, mais peut produire une plus grande byte[] que peut être strictement nécessaire pour votre scénario.
Si c'est le cas, vous pourriez utiliser la réflexion pour itérer sur les champs et/ou des propriétés de l'objet à sérialiser manuellement et de les écrire à la MemoryStream, l'appel de la sérialisation de manière récursive si nécessaire pour sérialiser non-trivial types. Cette méthode est plus complexe et prendra plus de temps à mettre en œuvre, mais permet beaucoup plus de contrôle sur la sérialisé flux.
Autre façon de convertir un objet de tableau d'octets:
Que penser de quelque chose de simple comme cela?
Je préfère utiliser l'expression "sérialisation" que "moulage en octets". La sérialisation d'un objet signifie de le convertir en un tableau d'octets (ou XML, ou autre chose) qui peut être utilisé sur la télécommande de la boîte à re-construire l'objet. Dans .NET, le
Serializable
l'attribut marques types dont les objets peuvent être sérialisés.Une autre mise en œuvre, qui utilise Newtonsoft.Json binary JSON et ne nécessite pas de marquage tout avec l'attribut [Serializable]. Un seul inconvénient est qu'un objet doit être enveloppé dans la classe anonyme, de sorte que le tableau d'octets obtenus avec la sérialisation binaire peut être différent de celui-ci.
Classe anonyme est utilisé parce que BFILS devrait commencer avec une classe ou d'un tableau.
Je n'ai pas essayé de désérialiser byte[] de retour à l'objet, et vous ne savez pas si il fonctionne, mais ont testé la vitesse de la conversion en byte[] et il correspond exactement à mes besoins.
Comment sur la sérialisation? jetez un oeil ici.