Gå til innhold

C#: [Løst] IsolatedStorage: WP7 - Uthenting av Liste


Anbefalte innlegg

Hei!

 

Jeg har et problem angående uthenting av en liste fra Isolated Storage.

 

For hver gang jeg legger til et nytt objekt til listen min, lagres det som et XML-dokument i IsolatedStorage som Courses.xml (se kode 1). Når jeg så skal hente det ut, deserializerer jeg xml dokumentet i konstruktøren og setter listen som dette deserializerte objektet og prøver å få printet det ut. Men her går det galt (Kode 2).

 

I følge debuggeren stopper koden ved følgende linje, gudene vet hvorfor....

 ListClass.SavedCourses = (List<Course>)serializer.Deserialize(stream);

 

(Kode 1: Lagring av objektet (fungerer så vidt jeg kan se))

public static void AddCourse(Course c)
    {	  
	    savedCourses.Add(c);
	    XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
	    xmlWriterSettings.Indent = true;
	    using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
	    {
		    using (IsolatedStorageFileStream stream = myIsolatedStorage.OpenFile("Courses.xml", FileMode.Create))
		    {
			    XmlSerializer serializer = new XmlSerializer(typeof(List<Course>));
			    using (XmlWriter xmlWriter = XmlWriter.Create(stream, xmlWriterSettings))
			    {
				    serializer.Serialize(xmlWriter, savedCourses);
			    }
		    }
	    }
    }


 

(Kode 2: Uthenting, fungerer ikke)

public MyCourses()
    {		 
	    InitializeComponent();
	    try
	    {
		    using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
		    {
			    using (IsolatedStorageFileStream stream = myIsolatedStorage.OpenFile("Courses.xml", FileMode.Open))
			    {
				    XmlSerializer serializer = new XmlSerializer(typeof(List<Course>));
				    //her tror jeg det går galt.
				    ListClass.SavedCourses = (List<Course>)serializer.Deserialize(stream);

			    }
		    }
	    }
	    catch
	    {
		    //kommer senere
	    }
	    if (ListClass.SavedCourses.Count == 0)
	    {
		    infoBox.Text = "Her var det tomt";
	    }
	    else
	    {
		    infoBox.Text = "Dine Kurs";
		    foreach (Course c in ListClass.SavedCourses)
		    {
			    String s = c.Id;
			    listBox1.Items.Add(s);
			    listBox2.Items.Add(c.Name);
		    }
	    }
	    }

 

Er det noen som kan hjelpe? Takk på forhånd! :)

Endret av xBANAN
Lenke til kommentar
Videoannonse
Annonse

Det er vel fordi du ikke har tatt med Courses som et objekt som kan serialiseres i constructoren til XmlSerializer.

 

Du burde forøvrig statisk initialisere XmlSerializers:

private static readonly XmlSerializer Serializer = new XmlSerializer(typeof(List&--#60;Courses&--#62;), typeof(Courses));

 

XmlSerializer er veldig dyr å opprette så ikke gjøre det mer enn nødvendig.

Endret av GeirGrusom
Lenke til kommentar

Tusen takk for svar GeirGrusom. Men jeg tror ikke det er dette som er problemet da jeg får lagret listen som et XML-dokument i IsolatedStorage.

 

Slik som dette ser nå hele klassen min ut. Jeg tenker at siden listen er statisk kan jeg bare ha alt sammen i en klasse, slik at alt lastes inn i den statiske klassen. Som sagt får vi lagret alt sammen som et xml-dokument, men ikke hentet det ut igjen etter at vi har lukket applikasjonen! :hmm:

 

Har du kanskje noen andre mulige løsninger? Eller er du helt sikker på at det er dette som er problemet? Takk for hjelp! :)

 

using System;
using System.Net;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Xml;
using System.Xml.Serialization;
using System.IO.IsolatedStorage;
using System.IO;
using System.Collections.Generic;

namespace Timeplan
{
   public class ListClass
   {

    static List<Course> savedCourses = new List<Course>();
    private static readonly XmlSerializer Serializer = new XmlSerializer(typeof(List<Course>));

    /**
	 * konstruktør
	 * henter ut Listen fra IsolatedStorage
	 */
    public ListClass()
    {
		 try
  {
   using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
   {
 using(IsolatedStorageFileStream stream = myIsolatedStorage.OpenFile("Courses.xml", FileMode.Open))
 {
				    savedCourses = (List<Course>)Serializer.Deserialize(stream);
 }
   }
  }
  catch
  {
   //add some code here
  }

    }

    public void AddCourse(Course c)
    {	  
	    savedCourses.Add(c);
	    // Write to the Isolated Storage
	    XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
	    xmlWriterSettings.Indent = true;
	    using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
	    {
		    using (IsolatedStorageFileStream stream = myIsolatedStorage.OpenFile("Courses.xml", FileMode.Create))
		    {
			    using (XmlWriter xmlWriter = XmlWriter.Create(stream, xmlWriterSettings))
			    {
				    Serializer.Serialize(xmlWriter, savedCourses);
			    }
		    }
	    }
    }

    public List<Course> SavedCourses
    {
	    get { return savedCourses; }
	    set { savedCourses = value; }
    }
    public Course getCourse(int index)
    {
	    Course s = savedCourses[index];
	    return s;
    }
    public Course getCourseByName(String name)
    {
	    for (int i = 0; i <= savedCourses.Count; i++)
	    {
		    Course c = savedCourses[i];
		    if(c.Id.Equals(name))
		    {
			    return c;
		    }
	    }
	    return null;
    }
   }
}


Endret av xBANAN
Lenke til kommentar

namespace Timeplan
{
   // Dummy minimum course
   public class Course
   {
    public string Id { get; set; }
   }
   public class ListClass
   {
    private const string CourseFilename = "Courses.xml";
    private static readonly XmlSerializer Serializer = new XmlSerializer(typeof(List<Course>), new Type[] { typeof(Course) });
    /// <summary>
    /// Course list constructor
    /// </summary>
    public ListClass()
    {
	    using (var myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
	    {
		    if (myIsolatedStorage.FileExists(CourseFilename))
		    {
			    using (var stream = myIsolatedStorage.OpenFile(CourseFilename, FileMode.Open))
			    {
				    SavedCourses = (List<Course>)Serializer.Deserialize(stream);
			    }
		    }
		    else
		    {
			    SavedCourses = new List<Course>();
		    }
	    }
    }

    public void AddCourse(Course c)
    {
	    SavedCourses.Add(c);
	    // Write to the Isolated Storage
	    var xmlWriterSettings = new XmlWriterSettings
	    {
		    Indent = true
	    };
	    using (var myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
	    {
		    using (var stream = myIsolatedStorage.OpenFile(CourseFilename, FileMode.Create))
		    {
			    using (var xmlWriter = XmlWriter.Create(stream, xmlWriterSettings))
			    {
				    Serializer.Serialize(xmlWriter, SavedCourses);
			    }
		    }
	    }
    }
    public List<Course> SavedCourses { get; private set; }
    public Course getCourse(int index)
    {
	    return SavedCourses[index];
    }

    public Course GetCourseByName(string name)
    {
	    return SavedCourses.FirstOrDefault(element => element.Id.Equals(name));
    }
   }
}

 

Du kan prøve dette. Ser du har en catch(exception) der som vil fjerne alle relevante feilmeldinger som er ganske uheldig i debug. Jeg la inn en test om filen eksisterer eller ikke, så hvis du får en exception der så er det fordi et eller annet er feil i koden din.

La også inn Course som en type til Serializeren, og noen forenklinger.

  • Liker 1
Lenke til kommentar

Jeg tror forøvrig du må deserializere til Course[] og ikke List<Course>. Mener å huske det er noe bøll med List<T> og deserialisering.

Det er i Soap serialisering som av en eller annen latterlig grunn ikke støtter generics.

 

Nja...problemet i akkurat dette tilfellet kan være at xmlen som er serialisert ikke er en valid xml siden han ikke har noe root element. Kan se ut som om at det bare blir appendet mange noder av Course. Jeg vet generic lists funker når den er wrappet i "rootklasse", men er litt usikker på om det funker som det er gjort her. Anyways...mulig du har rett. Tenkte det uansett var verdt et kjapt forsøk og deserialisere den som en array og ikke list.

Lenke til kommentar

Ojojoj! Overveldende mange svar nå! Tusen takk!

 

Har testet koden din nå geirgrusom, og får en exception på denne linjen:

 

SavedCourses = (List&--#60;Course&--#62;)Serialize.Deserialize(stream);

 

Da får jeg følgende exception:

 

"InvalidOperationException was unhandled

There is an error in XML document (3,4)"

 

Har googlet det, men fikk ikke noe godt svar.

 

Holder også nå på å prøve The Jackal sitt forslag for å se om det hjelper! :)

 

(PS: Beklager java-syntaks ettersom jeg egentlig er java-utvikler)

Endret av xBANAN
Lenke til kommentar

The Jackal: Indeed. Det er bare styggedom med funksjoner som returnerer arrays, så hvis en kan bruke List&--#60;T&--#62; så er det å foretrekke. Men absolutt verdt å prøve.

 

Derimot tror jeg problemet er at den ikke klarte å serialisere ut, men feilmeldingen ble dyttet tilside av try { ... } catch { } så det så bare ut som at serialisering funket.

Jeg tror at problemet er at XmlSerializer ikke ble servert Course typen (som er et krav for XmlSerializer).

 

Edit: kan se ut som det er noe annet i veien, men en feilmelding hjelper i det minste :)

Endret av GeirGrusom
Lenke til kommentar

public class Course
{
   public int Id { get; set; }
}

[XmlRoot(ElementName = "Courses")]
public class Courses : List<Course>;
{		
}

var courses = new Courses {new Course {Id = 1}, new Course {Id = 2}, new Course {Id = 3}};
var serializer = new XmlSerializer(typeof (Courses));
var memoryStream = new MemoryStream();
serializer.Serialize(memoryStream, courses);
memoryStream.Position = 0;
var serializer2 = new XmlSerializer(typeof(Courses));
var courses2 = (Courses)serializer2.Deserialize(memoryStream);
foreach (var course in courses2)
{
   Console.WriteLine(course.Id);
}
memoryStream.Close();
memoryStream.Dispose();

 

dette funker i alle fall :)

Endret av The Jackal
  • Liker 1
Lenke til kommentar

Jeg prøvde først å tilpasse det du skrev inn i koden min, men da fikk jeg denne feilmeldingen:

 

"InvalidOperationException was unhandled

There is an error in XML document (0, 0)."

 

Da det fremdels ikke fungerte prøvde jeg å direkte skrive akkurat det du skrev

inn i koden, men da kom følgende feilmelding opp igjen

 

"InvalidOperationException was unhandled

There is an error in XML document (3, 4)."

Lenke til kommentar

Etter mye prøving, feiling og kaffedrikking står jeg nå igjen med denne koden (se kode 1 og 2). Denne koden gjør som du The Jackal ønsker, lager et root element som heter Courses. Jeg får lagret XML dokumentet fint og vakkert. Men når jeg skal hente det ut går det ikke så bra. Det ser ut til å feile på linjen med

 

Data = (T)serializer.Deserialize(stream); (se kode 1)

 

Her får jeg opp samme feil som tidligere.

 

"InvalidOperationException was unhandled

There is an error in XML document (3, 4)."

 

Kode 1:

namespace Timeplan
{
   public class ListClass
   {
    [XmlRoot(ElementName = "Courses")]
    public class Courses : List<Course>
    {
    }
    static List<Course> savedCourses = new List<Course>();
    public ListClass()
    {
	    savedCourses = IsolatedStorageHelper.ReadFromXml<Courses>(IsolatedStorageHelper.MyObjectFile);
		    if (savedCourses == null)
		    {
			    List<Course> savedCourses2 = new List<Course>();
			    savedCourses = savedCourses2;
		    }
    }
    public static void AddCourse(Course c)
    {
	    savedCourses.Add(c);
	    var courses = new Courses { c };		  
	    IsolatedStorageHelper.WriteToXml(courses, IsolatedStorageHelper.MyObjectFile);

    }

    public static List<Course> SavedCourses
    {
	    get { return savedCourses; }
	    set { savedCourses = value; }
    }
    public static Course getCourse(int index)
    {
	    Course s = savedCourses[index];
	    return s;
    }
    public static Course getCourseByName(String name)
    {
	    for (int i = 0; i <= savedCourses.Count; i++)
	    {
		    Course c = savedCourses[i];
		    if (c.Id.Equals(name))
		    {
			    return c;
		    }
	    }
	    return null;
    }
   }

 

Kode 2:

namespace Timeplan
{
    public class IsolatedStorageHelper
    {
	    public const string MyObjectFile = "MyCourses.xml";
	    public static void WriteToXml<T>(T data, string path)
	    {
		    // Write to the Isolated Storage
		    var xmlWriterSettings = new XmlWriterSettings { Indent = true };
		    using (var myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
		    {
			    using (var stream = myIsolatedStorage.OpenFile(path, FileMode.Create))
			    {
				    var serializer = new XmlSerializer(typeof(T));
				    using (var xmlWriter = XmlWriter.Create(stream, xmlWriterSettings))
				    {
					    serializer.Serialize(xmlWriter, data);
				    }
			    }
		    }
	    }
	    public static T ReadFromXml<T>(string path)
	    {
		    T data = default(T);
		    try
		    {
			    using (var myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
			    {
				    using (var stream = myIsolatedStorage.OpenFile(path, FileMode.Open))
				    {
					    var serializer = new XmlSerializer(typeof(T));
					    data = (T)serializer.Deserialize(stream);
				    }
			    }
		    }
		    catch
		    {    //add some code here
		    }
		    return data;
	    }

   }
}

 

Tydeligvis er det ikke det ikke root-elementet som er feilen. Noen som ser problemet?

Lenke til kommentar

[XmlRoot(ElementName = "Courses")]
   public class Courses : List<Course>
   {
   }
   public class IsolatedStorageHelper
   {
    public const string MyObjectFile = "MyCourses.xml";
    public static void WriteToXml<T>(T data, string path)
    {
	    // Write to the Isolated Storage
	    var xmlWriterSettings = new XmlWriterSettings { Indent = true };
	    using (var myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
	    {
		    using (var stream = myIsolatedStorage.OpenFile(path, FileMode.Create))
		    {
			    var serializer = new XmlSerializer(typeof(T));
			    using (var xmlWriter = XmlWriter.Create(stream, xmlWriterSettings))
			    {
				    serializer.Serialize(xmlWriter, data);
			    }
		    }
	    }
    }
    public static T ReadFromXml<T>(string path)
    {
	    T data = default(T);
	    try
	    {
		    using (var myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
		    {
			    using (var stream = myIsolatedStorage.OpenFile(path, FileMode.Open))
			    {
				    var serializer = new XmlSerializer(typeof(T));
				    data = (T)serializer.Deserialize(stream);
			    }
		    }
	    }
	    catch
	    {    //add some code here
	    }
	    return data;
    }
   }
   public class ListClass
   {

    static Courses savedCourses = new Courses();
    static ListClass()
    {
	    savedCourses = IsolatedStorageHelper.ReadFromXml<Courses>(IsolatedStorageHelper.MyObjectFile);
    }
    public static void AddCourse(Course c)
    {
	    savedCourses.Add(c);
	    IsolatedStorageHelper.WriteToXml(savedCourses, IsolatedStorageHelper.MyObjectFile);
    }
    public static Courses SavedCourses
    {
	    get { return savedCourses ?? (SavedCourses = new Courses()); }
	    set { savedCourses = value; }
    }
    public static Course getCourse(int index)
    {
	    Course s = savedCourses[index];
	    return s;
    }
    public static Course getCourseByName(String name)
    {
	    for (int i = 0; i <= savedCourses.Count; i++)
	    {
		    Course c = savedCourses[i];
		    if (c.Id.Equals(name))
		    {
			    return c;
		    }
	    }
	    return null;
    }
   }

 

Bare rettet opp de mest åpenbare feilene, men har ikke testet det.

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...