Piszę prototypowe połączenie TCP i mam problem z ujednoliceniem wysyłanych danych.
W tej chwili wysyłam tylko napisy, ale w przyszłości chcemy mieć możliwość wysyłania dowolnego obiektu.
Kod jest w tej chwili dość prosty, ponieważ myślałem, że wszystko można rzucić na tablicę bajtów:
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[]'.
...
}
Oczywiście można to łatwo rozwiązać za pomocą pliku
if( state.headerObject is System.String ){...}
Problem polega na tym, że jeśli robię to w ten sposób, muszę sprawdzić KAŻDY typ obiektu, którego nie można rzutować na bajt [] w czasie wykonywania.
Ponieważ nie znam każdego obiektu, którego nie można wrzucić do bajtu [] w czasie wykonywania, tak naprawdę nie ma takiej opcji.
Jak przekonwertować dowolny obiekt na tablicę bajtów w C # .NET 4.0?
FileStream
lub dowolny obiekt, który zawiera taki uchwyt).Odpowiedzi:
Użyj
BinaryFormatter
:Zauważ, że
obj
i wszystkie właściwości / pola w obrębieobj
(i tak dalej dla wszystkich ich właściwości / pól) będą musiały być oznaczoneSerializable
atrybutem, aby pomyślnie zserializować z tym.źródło
using
bloku, ponieważ chętnie zwolni on używany wewnętrzny bufor.sprawdź ten artykuł: http://www.morgantechspace.com/2013/08/convert-object-to-byte-array-and-vice.html
Użyj poniższego kodu
źródło
MemorySteam
powinien on być umieszczony wusing
bloku.Tak jak inni powiedzieli wcześniej, możesz użyć serializacji binarnej, ale może ona wygenerować dodatkowe bajty lub zostać zdeserializowana do obiektów z nie dokładnie tymi samymi danymi. Z drugiej strony korzystanie z refleksji jest dość skomplikowane i bardzo powolne. Istnieje inne rozwiązanie, które może ściśle konwertować twoje obiekty na bajty i vice versa - marshalling:
I przekonwertować bajty na obiekt:
Jest to zauważalnie wolniejsze i częściowo niebezpieczne, aby używać tego podejścia do małych obiektów i struktur w porównaniu do własnej serializacji pole po polu (z powodu podwójnego kopiowania z / do niezarządzanej pamięci), ale jest to najłatwiejszy sposób na ścisłą konwersję obiektu na bajt [] bez implementowania serializacji i bez atrybutu [Serializable].
źródło
StructureToPtr
+Copy
jest powolny? Jak to może być wolniejsze niż serializacja? Czy jest jakieś szybsze rozwiązanie?var bytes = new byte[size];
To, czego szukasz, to serializacja. Na platformie .Net dostępnych jest kilka form serializacji
byte[]
źródło
Możesz go użyć jak poniżej kodu.
źródło
Używanie
Encoding.UTF8.GetBytes
jest szybsze niż używanieMemoryStream
. Tutaj używam NewtonsoftJson, aby przekonwertować obiekt wejściowy na ciąg JSON, a następnie pobrać bajty z ciągu JSON.Benchmark dla wersji @Daniel DiPaolo z tą wersją
źródło
Połączone rozwiązania w klasie Extensions:
źródło
Można użyć wbudowanych narzędzi serializacji w ramach i serializować do MemoryStream . Może to być najprostsza opcja, ale może generować większy bajt [], niż może to być absolutnie konieczne w Twoim scenariuszu.
W takim przypadku można użyć odbicia do iteracji po polach i / lub właściwościach obiektu, który ma zostać serializowany, i ręcznie zapisać je w MemoryStream, wywołując cykliczne wywołanie serializacji w razie potrzeby w celu serializacji nietrywialnych typów. Ta metoda jest bardziej złożona i jej wdrożenie zajmie więcej czasu, ale umożliwia znacznie większą kontrolę nad serializowanym strumieniem.
źródło
A może coś tak prostego?
źródło
Wolę raczej użyć wyrażenia „serializacja” niż „rzutowanie na bajty”. Serializacja obiektu oznacza konwersję go na tablicę bajtów (lub XML lub coś innego), której można użyć na zdalnym urządzeniu do ponownego skonstruowania obiektu. W .NET
Serializable
atrybut oznacza typy, których obiekty mogą być serializowane.źródło
Alternatywny sposób konwersji obiektu na tablicę bajtów:
źródło
Jedna dodatkowa implementacja, która korzysta z binarnego formatu JSON Newtonsoft.Json i nie wymaga oznaczania wszystkiego atrybutem [Serializable]. Jedyną wadą jest to, że obiekt musi być opakowany w anonimową klasę, więc tablica bajtów uzyskana za pomocą serializacji binarnej może się różnić od tej.
Używana jest klasa anonimowa, ponieważ BSON powinien zaczynać się od klasy lub tablicy. Nie próbowałem deserializować bajtu [] z powrotem do obiektu i nie jestem pewien, czy to działa, ale przetestowałem szybkość konwersji na bajt [] i całkowicie spełnia moje potrzeby.
źródło
A co z serializacją? spójrz tutaj .
źródło