Jaka jest najbardziej elastyczna serializacja for.NET obiekty, ale proste w implementacji?

Chciałbym serializować i deserializować obiekty bez martwienia się o cały wykres klasy.

Elastyczność jest kluczowa. Chciałbym móc serializować dowolny obiekt przekazany do mnie bez pełnych atrybutów potrzebnych w całym wykresie obiektu.

Oznacza to, że serializacja binarna nie jest opcją, ponieważ działa tylko z pozostałe platformy. NET. Ja bym również jak coś czytelnego przez osoby, a tym samym rozszyfrowane przez zarządzanie program i inne Tłumacze.

Znalazłem problemy przy użyciu Serializerów DataContract, JSON i XML.

  • większość tych błędów wydaje się skupiać wokół serializacji list/słowników (np. XML Serializable Generic Dictionary).
  • "Dodaj dowolne typy nie znane statycznie do listy znanych typów-dla przykład, korzystając z KnownTypeAttribute atrybut or by dodanie ich do listy znanych rodzaje zaliczone na DataContractSerializer."

Proszę oprzeć swoje odpowiedzi na rzeczywistych doświadczeń, a nie teorii lub czytania artykułu.

Author: James Newton-King, 2008-09-20

12 answers

Czy rozważałeś serializowanie do JSON zamiast XML?

Json.NET ma naprawdę potężny i elastyczny serializer, który nie ma problemów z Hashtablami/ogólnymi słownikami i nie wymaga żadnych szczególnych atrybutów. Wiem, bo to napisałem:)

Daje Ci mnóstwo kontroli poprzez różne opcje w serializatorze i pozwala nadpisać sposób serializacji typu, tworząc dla niego JsonConverter.

Moim zdaniem JSON jest bardziej ludzki czytelny niż XML i Json.NET daje możliwość napisania ładnie sformatowanego JSON.

Wreszcie projekt jest open source, więc możesz wkroczyć do kodu i dokonać modyfikacji, jeśli zajdzie taka potrzeba.

 53
Author: James Newton-King,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 02:32:51

Jeśli dobrze pamiętam to działa coś takiego z właściwością:

[XmlArray("Foo")]
[XmlArrayItem("Bar")]
public List<BarClass> FooBars
{ get; set; }

Jeśli seryjnie to dostaniesz coś w stylu:

<Foo>
    <Bar />
    <Bar />
</Foo>

Oczywiście, prawdopodobnie powinienem zdać się na ekspertów. Oto więcej informacji od MS: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlarrayitemattribute.aspx

Daj mi znać, jeśli ci się uda.
 3
Author: Ian Suttle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 01:23:08

Z twoich wymagań wygląda na to, że serializacja Xml jest najlepsza.

Jakie masz problemy ze zbiorami podczas serializacji? Jeśli chodzi o to, że nie wiesz, jakich atrybutów użyć na liście lub czymś podobnym, możesz spróbować Atrybut xmlarray na twojej własności. Możesz zdecydowanie serializować kolekcję.

 2
Author: Ian Suttle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 01:02:19

IntermediateSerializer w frameworku XNA jest cholernie fajny. Możesz znaleźć kilka samouczków na temat korzystania z niego w http://blogs.msdn.com/shawnhar

 1
Author: TraumaPony,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 00:47:59

Serializacja SOAP działała dobrze dla mnie, nawet dla obiektów Nie oznaczonych [Serializable]

 1
Author: ripper234,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 00:51:08

Będziesz miał problemy z serializacją kolekcji, jeśli obiekty w kolekcji zawierają jakiekolwiek odniesienia do innych obiektów w tej samej kolekcji. Jeśli istnieje jakikolwiek rodzaj podwójnego Wskazywania, w końcu tworzysz wiele map, których nie można serializować. W przypadku każdego problemu, jaki kiedykolwiek miałem serializowanie kolekcji niestandardowej, to zawsze z powodu jakiejś dodatkowej funkcjonalności, której potrzebowałem, działało dobrze jako część "typowej" aplikacji klient-serwer, a następnie nie powiodło się jako część aplikacja consumer-provider-server.

 1
Author: Jarrett Meyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 01:22:07

Umieść wszystkie klasy, które chcesz serializować w osobnym zestawie, a następnie użyj narzędzia sgen do wygenerowania zestawu serializacji w celu serializacji do XML. Użyj atrybutów XML do kontrolowania serializacji.

Jeśli chcesz dostosować montaż serializacji (a będziesz potrzebował tego do obsługi klas, które nie są Ixmlserializowalne i klas zawierających abstrakcyjne węzły), poinstruuj sgen, aby zrzut kodu źródłowego do osobnego pliku i następnie dodaj go do swojego rozwiązania. Wtedy możesz go zmodyfikować w razie potrzeby.

Http://msdn.microsoft.com/en-us/library/bk3w6240 (VS. 80). aspx

FWIW, za pomocą tej techniki udało mi się serializować cały Framework AdsML (ponad 400 klas). Wymagało to dużo ręcznego dostosowywania, ale nie da się tego obejść, jeśli wziąć pod uwagę rozmiar frameworka. (Użyłem osobnego narzędzia, aby przejść z XSD do C#)

 1
Author: ilitirit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 01:54:43

Zgadzam się, że metody serializacji oparte na DataContract (do JSON, XML, itp.) są nieco bardziej złożone niż bym chciał.

If you ' re trying to get JSON check out http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx

Jest częścią rozszerzeń MS AJAX. Co prawda jest oznaczony jako przestarzały w. NET 3.5, ale ScottGu wspomina w swoim komentarzu na blogu tutaj (http://weblogs.asp.net/scottgu/archive/2007/10/01/tip-trick-building-a-tojson-extension-method-using-net-3-5.aspx#4301973), że nie jest pewien dlaczego i powinien być obsługiwany nieco dłużej.

 1
Author: Aaron Powell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 10:07:05

Najprostszą rzeczą do zrobienia jest oznaczenie obiektów atrybutem Serializable, a następnie użycie binarnego formatera do obsługi serializacji. Cały wykres klasy nie powinien stanowić problemu pod warunkiem, że wszystkie zawarte obiekty są również oznaczone jako Serializowalne.

 0
Author: Ben Hoffstein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 00:47:51

Być może bardziej efektywną drogą byłoby serializowanie za pomocą BinaryFormatter

Jak skopiowano z http://blog.paranoidferret.com/index.php/2007/04/27/csharp-tutorial-serialize-objects-to-a-file/

using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

public class Serializer
{
   public Serializer()
   {
   }

   public void SerializeObject(string filename,
                  ObjectToSerialize objectToSerialize)
   {
      Stream stream = File.Open(filename, FileMode.Create);
      BinaryFormatter bFormatter = new BinaryFormatter();
      bFormatter.Serialize(stream, objectToSerialize);
      stream.Close();
   }

   public ObjectToSerialize DeSerializeObject(string filename)
   {
      ObjectToSerialize objectToSerialize;
      Stream stream = File.Open(filename, FileMode.Open);
      BinaryFormatter bFormatter = new BinaryFormatter();
      objectToSerialize =
         (ObjectToSerialize)bFormatter.Deserialize(stream);
      stream.Close();
      return objectToSerialize;
   }
}
 0
Author: Greg Ogle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 02:14:54

Dla interoperacyjności zawsze używaliśmy serializacji Xml i upewniliśmy się, że nasza klasa została zaprojektowana od podstaw, aby zrobić to poprawnie.

Tworzymy dokument schematu XSD i generujemy z niego zestaw klas za pomocą XSD.exe. Generuje to klasy częściowe, więc następnie tworzymy zestaw odpowiadających im klas częściowych, aby dodać dodatkowe metody, które chcemy pomóc nam wypełnić klasy i użyć ich w naszej aplikacji (ponieważ koncentrują się one na serializacji i deserializacji i są nieco trudne do użycia czasami).

 0
Author: Brody,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 02:44:42

Powinieneś użyć NetDataContractSerializer. Obejmuje każdy rodzaj grafu obiektowego i obsługuje generyki, listy, polimorfizm( atrybut KnownType nie jest tu potrzebny), rekurencję itp. Jedyną wadą jest to, że musisz oznaczyć wszystkie klasy atrybutami [Serializable] / [DataContract], ale doświadczenie pokazuje, że musisz zrobić jakiś rodzaj ręcznego dostrajania, ponieważ nie wszyscy członkowie powinni być wytrwali. Również serializuje się do Xml, choć jego czytelność jest wątpliwe.

Mieliśmy takie same wymagania jak twoje i wybraliśmy to rozwiązanie.

 0
Author: adams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 09:56:36