Jan.30

Objecten & objectstructuren opslaan als bestand

In dit artikeltje wil ik je laten zien hoe je gemakkelijk door middel van 2 methoden objectgegevens binair in een file op kunt slaan en weer op kunt halen. Er zijn heel wat artikelen aan serialization gewijdt. Deze gaan veel dieper als dit artikeltje. In dit geval gaat het erom hoe serialiseren en deserialiseren we op een simpele, snelle en correcte manier.

Het opslaan van een object of een objectstructuur als bestand is al mogelijk sinds de eerste versie van het .NET framework. Met een duur woord heet dit serialization (opslaan) en deserialization (ophalen/laden). Het opslaan als bestand is 1 vorm maar je kunt bijvoorbeeld de gegevens ook in een MemoryStream of bijv. de Application State van een ASP.NET applicatie opslaan. Verder is de vorm waarmee de gegevens worden opgeslagen te bepalen. Twee van de mogelijkheden zijn binair of in XML formaat. Dit laatste heeft wat nadelen aangezien niet alle gegevens van een object kunnen worden opgeslagen.

Voorwaarden
Een voorwaarde om een object op te kunnen slaan is dat de betreffende class voorzien is van het attribuut [Serializable]. Dus…

[Serializable] public class AClass
{
...
}

Op het moment dat een instantie (object) van deze class wordt geserializeerd. Dan zullen ook alle gerelateerde velden (properties) worden geserializeerd. Stel…

[Serializable] public class Employee
{
public Address HomeAddress;
...
}

public class Address
{
public string Street;
public string HouseNr;
public string Zip;
}

We hebben dus een werknemer (employee) met daaraan gekoppeld een thuis adres (HomeAddress). Op het moment dat we Employee serializeren zal ook het HomeAddress worden geserializeerd. In dit voorbeeld zal dit echter een exception opleveren aangezien de Address class niet het serializable attribuut bevat.


[Serializable] public class Address
{
...

Bovenstaande code is dus wel OK. Het is overigens ook mogelijk velden expliciet niet mee te laten serializeren. Dit kan worden geregeld door het NonSerialized attribuut te zetten op het specifieke veld.


[Serializable] public class Employee
{
[NonSerialized] public Address HomeAddress;
...
}

In bovenstaande geval hoeft de Address class dus ook het attribuut serializable niet te bevatten.

Verder is het van belang in de gaten te houden dat als een object of objectstructuur is geserializeerd en een class in de objectstructuur wordt daarna aangepast, de geserializeerde gegevens niet meer kunnen worden opgehaald. De binaire gegevens kunnen dan niet meer gemapped worden op het aangepaste type.

Wanneer?
Wanneer is serializatie handig om te gebruiken? Stel je hebt een WinForms applicatie geschreven waarbij je ingevoerde gegevens in een soort projectbestand op wilt slaan. Hiervoor kun je prima binaire serializatie gebruiken.

Ook kan het handig zijn bij webapplicaties. Zo is het bijvoorbeeld mogelijk via SQL Management Objects (SMO), alle mogelijke gegevens van een SQL database (tabellen, velden, primary keys, foreign keys, indexen etc…) op te halen dit proces vergt echter flink wat tijd. Je zou in dat geval een objectstructuur kunnen creeeren bij het ophalen van deze gegevens die overeenkomt met de databaseindeling. Deze structuur vervolgens serializeren naar een bestand en deze vervolgens bij elke request inlezen om gegevens over de database te verkrijgen. Dit kan natuurlijk alleen als de database qua structuur niet wijzigt.

Verder heeft binair opslaan (en dan niet perse als bestand) in sommige gevallen voordelen boven het vasthouden van een referentie naar een object of objectstructuur. Je kunt hiermee objecten of objectstructuren dupliceren.

De code
Ter zake. Hieronder vindt je de code waarmee een object of objectstructuur kan worden opgeslagen op schijf en weer opgehaald. Het mooie is dat bij het ophalen niet noodzakelijk is te weten welk objecttype er terug wordt gegeven.

LET OP: Via de printversie (links boven en onder) kun je de code kopieren.

De code kan dus alsvolgt worden gebruikt:

//Opslaan
Employee emp = new Employee()
emp.Name = "Ton Snoei";
...
SerializeObject(emp,@"c:test.bin");

//ophalen
Employee x = (Employee) DeSerializeObject(@"c:test.bin");

Deel dit Verhaal:
  • facebook
  • twitter
  • gplus

Over Ton Snoei

Een enthousiaste ontwikkelaar in de allerbreedste zin van het woord.

Het aansturen maar vooral coachen van mensen geeft me veel plezier en een leuke uitdaging. Ik houdt me graag bezig met het bouwen van software maar ook met alle anderen dingen die komen kijken bij het vak dat IT heet.

Met als achtergrond ontwikkelaar heb ik veel ervaring met C# .NET en alles wat daarbij komt kijken. Deze kennis komt nog regelmatig goed van pas. Mijn liefde voor ontwikkeling van software is nooit verdwenen en heb mij daarom in het afgelopen jaar meer verdiept in Java, Android, iOS/iPhone/iPad (Monotouch/Xamarin), PHP en Unity 3D development. Ik noem dat altijd maar: "Lego-spelen voor grote mensen" ;-)

Kortom van de grote lijnen naar projecten tot hands-on problem solven.

Laat een reactie achter

Comment