|
RHS |
TouristicRental04
Det er ikke specielt smukt at Init() (i Shop.cs) danner indholdet af vores cykel-liste hver gang vi kører programmet.
Så lad os gemme listen af cykler i en fil så vi kan indlæse dem istedet for at danne listen forfra.
Moderne OO-sprog kan serialisere praktisk talt enhver struktur af objekter (se f.eks. kap. 15.4).
For at objekter kan serialiseres skal klassen markeres med en attribut: [Serializable]- se kap. 15.1.
Det er heldigvis ikke svært: Skriv blot teksten [Serializable] umiddelbart før selve klassens header, f.eks.:
[Serializable]
public abstract class Bicycle {
...
}
Gør klasserne Bicycle, CityBike og SportsBike serializable!
I den klasse hvor selve serialiseringen udføres skal vi have fat i et par biblioteker.
Tilføj nedenstående til klassen Shop:
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
Vi vil nu benytte Init() til at danne filen af cykler ved at gemme listen bicycles i en fil (cykler.dat).
Det skal kun gøres een gang, så det letteste er blot at udkommentere kommandoen shop.Open() i metoden Main() (så er det kun Init() som aktiveres).
I Init() skal vi danne listen som sædvanligt, men herefter skal den gemmes på fil.
Det klarer følgende kode:
//Declared outside try{} so it can be seen by finally{}
FileStream stream = null;
try {
stream = new FileStream("cykler.dat", FileMode.Create);
IFormatter format = new BinaryFormatter();
format.Serialize(stream, bicycles);
}
catch (SerializationException e) {
Console.WriteLine("erialization error. \nReason: " + e.Message);
}
catch (IOException e) {
Console.WriteLine("IO error. \nReason: " + e.Message);
}
catch (Exception e) {
Console.WriteLine("Other error. \nReason: " + e.Message);
}
finally {
if (stream != null) stream.Close();
}
Bemærk at stream erklæres udenfor try-blokken idet den ellers ville være udenfor scope af finally-blokken.
Til gengæld konstrueres selve objektet først i try-blokken idet der kan opstå fejl (f.eks. hvis filen eksisterer i forvejen OG er skrivebeskyttet).
Til almindelig serialisering benyttes en binær formatter, hvis metode Serialize() "hælder" et objekt med alle andre tilknyttede objekter ud på en stream.
Da der kan opstå div. exceptions ifm. serialisering, fil-behandling o.a. (se i dokumentationen for alle de mulige exceptions der kan opstå) er catch-blokken ret restriktiv. Efter et par specifikke "catchs" vil sidste catch fange alt!
Bemærk også at der skal testes på om stream'en overhovedet blev oprettet inden den forsøges lukket.
Ovenstående kode skal kun udføres een gang så har vi filen med indhold.
Herefter kan koden slettes - eller udkommenteres.
Husk også at slette eller udkommentere den kode som danner listen "manuelt".
Nu skal Init() så til gengæld ændres til at læse indholdet fra filen ind i listen bicycles igen - og det skal den gøre hver gang programmet startes.
Læsning (eller deserialisering) forgår næsten på samme måde. De væsentligste forskelle er:
Nu skulle dit program kunne køre og indlæse data fra filen (som iøvrigt findes i mappen <projektmappe>/bin/debug).
Husk at fjerne udkommenteringen af shop.Open() igen.
Hvis du er modig kan du gemme listen af Rental-objekter. Overvej hvilke problemer (eller uhensigtsmæssigheder) det kan give?