Med vad ska man serialisera?

2011-10-04

Alla vägar bär inte till Rom om ens någon gör det.

Idag skulle jag lägga till möjligheten att spara sökningar, och i förlängningen skapa bevakningar utifrån dessa sökningar. Den givna vägen att gå var att använda serialisering för att spara sökbojekten. Idén med serialisering är att man ska kunna spara undan ett objekt och sedan plocka fram det igen. Detta utan att objektet har förändrats. Ungefär som Stallone och Snipes i Demolition Man. I mitt fall handlar det om enstaka sökningar med allt vad de innehåller av avgränsningar, vilken söktjänst som är den primära, antalet returnerade träffar mm. Jag trodde serialisering av objekt i .NET var en enkel match. Det skulle visa sig vara lite svårare i realiteten.

Traditionellt finns det två vägar att gå om man vill serialisera ett objekt i .NET: XML-serialisering eller serialisering i binärformat. XML-serialiseringen har den fördelen att man kan titta på objektet i databasen och förstå vad det är man sparat. Detta kan man svårligen med binärkod. Därför var XML-serialiseringen mitt förstahandsval. Ungefär så här skulle en funktion för att XML-serialiesera en sökfråga sett ut:

{syntaxhighlighter brush:csharp} public static string XMLSerialize(this SingleQuery singleQueryToSerialize) { System.Xml.Serialization.XmlSerializer writer =new System.Xml.Serialization.XmlSerializer(typeof(SingleQuery)); System.IO.StringWriter yStringWriter = new System.IO.StringWriter(); writer.Serialize(myStringWriter, singleQueryToSerialize); return myStringWriter.ToString(); } {/syntaxhighlighter}

Ganska snart så visade det sig att .NET-ramverket inte tillåter serialisering av Dictionary-datatypen när man serialiserar till XML, och detta är en datatyp jag inte kan vara utan. Det finns mängder med tips om hur man går runt detta, men jag valde att avstå, då ingen var varken särskilt elegant eller lätt att förstå. Duh.

Nästa försök var att serialisera binärt. Koden för detta är ännu enklare:

{syntaxhighlighter brush:csharp} MemoryStream memStream = new MemoryStream(); StreamWriter sw = new StreamWriter(memStream); sw.Write(ObjectToSerialize); memStream.GetBuffer(); {/syntaxhighlighter}

Återigen högg jag i sten och fick se mig slagen. Denna gång på grund av att vårt webbpubliceringssystem Umbraco:s databaskopplingar inte tillåter binärdata i det man skickar. Man kan inte sätta datatyp när man skapar parametrar för parameteriserade frågor. Jag gissar att det har med Umbracos fria databasval att göra.

Så vad göra? Då kom jag på att jag nyligen fick frågan om hur Umbraco hanterar JSON-objekt. Jag kollade upp om .NET har något inbyggt, vilket det har. Tidigare var man tvungen att använda externa projekt för att arbeta med JSON, men sedan version 3.5 räcker det med att bara lägga in en referens till System.Web.Extensions så finns där en JavaScriptSerializer att tillgå. Koden för att serialisera ser ut så här:

{syntaxhighlighter brush:csharp} using System.Web.Script.Serialization; JavaScriptSerializer serializer = new JavaScriptSerializer(); string serializeQuery = serializer.Serialize(query);{/syntaxhighlighter}

En annan trevlig sak med .NET som jag missbrukar alldeles för mycket är Uppräkningstyper (Enums). De, tycker jag, bidrar till mycket mer lättläslig kod. Tyvärr kan man inte serialisera Enums.Edit: jo det kan man. Edit: Jo, det kan man,Det löstes med att jag ersatte mina enums med strängrepresentationer av dem på så få ställen som möjligt. Se nedanstående exempel (QueryableFields är en Enum):

{syntaxhighlighter brush:csharp} QueryableFields.Title.ToString();{/syntaxhighlighter}

och

{syntaxhighlighter brush:csharp} (QueryableFields) Enum.Parse(typeof(QueryableFields),field){/syntaxhighlighter}

Jag vet inte om det är hållbart i längden, men det fungerar just nu. På sikt får jag nog se över det.

Edit:Följ gärna min relaterade fråga på Stack Overflow i ämnet

/Bibliotekarien - The Librarian