I am having a hell of a time getting a variable from the function of another class usable in my Game1 (main) class. Specifically, I want to take width and height from the function SaveData in SetWindowSize.cs and use it in ReadSettings in Game1.cs.
I get the error
'ShovelShovel.SetWindowSize' does not contain a definition for
'height'. Same for 'width'.
Game1.cs (the function only)
protected void ReadSettings()
{
try
{
if (File.Exists(SetWindowSize.savePath))
{
using (FileStream fileStream = new FileStream(SetWindowSize.savePath,
FileMode.Open))
{
using (BinaryReader binaryReader = new BinaryReader(fileStream))
{
SetWindowSize.width = binaryReader.ReadInt32();
SetWindowSize.height = binaryReader.ReadInt32();
}
}
}
}
catch
{
}
}
SetWindowSize.cs
namespace ShovelShovel
{
protected void ReadSettings()
{
try
{
if (File.Exists(savePath))
{
using (FileStream fileStream = new FileStream(savePath, FileMode.Open))
{
using (BinaryReader binaryReader = new BinaryReader(fileStream))
{
var windowSize = WindowSizeStorage.ReadSettings();
WindowSize.Width = windowSize.Width;
WindowSize.Height = windowSize.Height;
}
}
}
}
catch
{
}
}
Thank you so much to anyone and everyone that can help me, I really appreciate it.
This might do the trick:
public class WindowSize
{
public int Width { get; set; }
public int Height { get; set; }
}
public static class WindowSizeStorage
{
public static string savePath = "WindowSize.dat";
public static WindowSize ReadSettings()
{
var result = new WindowSize();
using (FileStream fileStream = new FileStream(SetWindowSize.savePath, FileMode.Open))
{
using (BinaryReader binaryReader = new BinaryReader(fileStream))
{
result.Width = binaryReader.ReadInt32();
result.Height = binaryReader.ReadInt32();
}
}
return result;
}
public static void WriteSettings(WindowSize toSave)
{
using (BinaryWriter binaryWriter = new BinaryWriter(File.Open(savePath, FileMode.Create)))
{
binaryWriter.Write(toSave.Width);
binaryWriter.Write(toSave.Height);
}
}
}
Usage:
// Read
var windowSize = WindowSizeStorage.ReadSettings();
myForm.Width = windowSize.Width;
myForm.Height = windowSize.Height;
// Write
var windowSize = new WindowSize { Width = myForm.Width, Height = myForm.Height };
WindowSizeStorage.WriteSettings(windowSize);
Please note that writing an answer like this (presenting all code) is not the common way; I just felt like it. I tried to show some object-oriented design principles, where each class does its own thing.
If you want to transfer compicated objects between methods (i.e. more than one primitive type), you will usually create a Data Transfer Object (DTO) like WindowSize.
The WindowSizeStorage class has the sole responsibility to store and retreive such a WindowSize object. From your code you simply tell the storage to store or retreive the settings you wish.
But as I get from your question and comments, you haven't got much experience using C# or perhaps any programming experience at all. Try to pick up on a tutorial or two so you can understand how to put your thoughts into code.
You cannot access Function variable outside that function.
To achieve these define static variable assign height and width to the static variable then access it wherever you want.
A function's purpose is not to store and expose variables. You can't access variables if their scope is not wide enough. In your case, you should expose those in a way or another by storing them in the class and making them public, for example :
class SetWindowSize
{
public const string savePath = "file.dat";
public int width {get; set; }
public int height {get; set; }
public static void SaveData(string width, string height)
{
using (BinaryWriter binaryWriter = new BinaryWriter(File.Open(savePath, FileMode.Create)))
{
binaryWriter.Write(width);
binaryWriter.Write(height);
SetWindowSize.width = width;
SetWindowSize.height = height;
}
}
}
}
That is far from optimal, but it works.
Your SetWindowSize class does not contain width or height members. You can add them as properties:
public class SetWindowSize
{
// other stuff
public int Height {get;set;}
public int Width {get;set;}
// other stuff
}
Then you can access them using the SetWindowSize instance:
SetWindowSize sws = new SetWindowSize();
sws.Height = 512;
sws.Width = 512;
Related
I'm nearly done making my mobile game and I have have a DATA script using what is shown in this video. I have a list which holds the values of different challenges that the player can complete. How would I update the game so that I can add more challenges whilst still keeping the old data.
(The challenge data basically contains whether it has been completed and how far off being completed it is)
I have had a look at this guide but I don't quite understand it. I'm new to serialization.
Thank you in advance :)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
[System.Serializable]
public class XMLManager : MonoBehaviour {
public static XMLManager dataManagement;
public gameData data;
void Awake()
{
//File.Delete(Application.dataPath + "/StreamingFiles/XML/item_data.xml");
System.Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");
dataManagement = this;
DontDestroyOnLoad(gameObject);
}
public void SaveData()
{
XmlSerializer serializer = new XmlSerializer(typeof(gameData));
System.Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");
FileStream stream = new FileStream(Application.dataPath + "/StreamingFiles/XML/item_data.xml", FileMode.Create);
serializer.Serialize(stream, data);
stream.Close();
}
public void LoadData()
{
System.Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");
if (File.Exists(Application.dataPath + "/StreamingFiles/XML/item_data.xml"))
{
XmlSerializer serializer = new XmlSerializer(typeof(gameData));
FileStream stream = new FileStream(Application.dataPath + "/StreamingFiles/XML/item_data.xml", FileMode.Open);
data = serializer.Deserialize(stream) as gameData;
stream.Close();
}
else
{
print("SaveData");
SaveData();
}
}
}
[System.Serializable]
public class gameData
{
public List<ChallengeStatus> Challenges;
public int HighScore;
public int CoinsCollected;
public List<bool> Unlocked;
public int GamesPlayed;
public int currentChallenge;
}
[System.Serializable]
public class ChallengeStatus
{
public int id;
public string title;
public int current;
public int max;
public int reward;
public bool completed;
public bool claimed;
}
First you should have a look at Unity XML Serialization and use proper attributes. You don't totally need them (except maybe the [XmlRoot]) but they let you customize your Xml file. If not provided Unity uses the variable names and uses sub-elements instead of attributes. However afaik this works only for primitives (int, float, string, bool, etc) and lists of them not for your own class ChallengeStatus. So at least for the list of your class you have to provide attributes:
[System.Serializable]
[XmlRoot("GameData")]
public class GameData
{
[XmlArray("Challenges")]
[XmlArrayItem("ChallengeStatus)]
public List<ChallengeStatus> Challenges;
//...
}
Now I don't really understand why you need to keep the old XML file when saving a new one but if you want to keep the current file I would add an int FileCounter .. ofcourse not in the same XML file ;) Might be e.g. via PlayerPrefs or a second simple text file only including the number or something similar.
Note it is better/saver to use Path.Combine for concatenate systempaths) - the overload taking an array of strings requires .Net4. Something like
private string FilePath
{
get
{
//TODO first load / read the FileCounter from somewhere
var paths = {
Application.dataPath,
"StreamingFiles",
"XML",
// here you get from somewhere and use that global FileCounter
string.Format("item_data_{0}.xml", FileCounter)};
return Path.Combine(paths);
}
}
Than you can increase that global FileCounter everytime you save the file.
public void SaveData()
{
//TODO somehow increase the global value
// store to PlayerPrefs or write a new file or ...
FileCounter += 1;
System.Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");
// better use the "using" keyword for streams
// use the FilePath field to get the filepath including the filecounter
using(FileStream stream = new FileStream(FilePath, FileMode.Create))
{
XmlSerializer serializer = new XmlSerializer(typeof(gameData))
serializer.Serialize(stream, data);
}
}
And read the file with the current FileCounter without increasing it
public void LoadData()
{
System.Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");
if (File.Exists(FilePath))
{
// better use a "using" block for streams
// use the FilePath field to get the filepath including the filecounter
using(FileStream stream = new FileStream(FilePath, FileMode.Open))
{
XmlSerializer serializer = new XmlSerializer(typeof(gameData));
data = serializer.Deserialize(stream) as gameData;
}
}
else
{
print("SaveData");
SaveData();
}
}
Hint 1:
As soon as you provide a constructor for your classes e.g.
public GameData(List<ChallengeStatus> challenges)
{
Challenges = challenges;
}
than you always have to also provide a default constructor (even if it does nothing)
public GameData(){ }
Hint 2:
You should always initialize your lists:
public class GameData
{
public List<ChallengeStatus> Challenges = new List≤ChallangeStatus>();
//...
public List<bool> Unlocked = new List<bool>();
//...
}
Hint 3:
Btw you don't need that [System.Serializable] for XmlManager since it inherits from MonoBehaviour which already is serializable anyway.
I am using a simple method of serializing and deserializing data for my save files which looks like this
//Object that is being stored
[System.Serializable]
public class GameData{
public int units;
public int scanRange;
public int gains;
public int reputation;
public int clicks;
public Dictionary<string,bool> upgradesPurchased;
public Dictionary<string,bool> upgradesOwned;
public Dictionary<string,bool> achievementsEarned;
public GameData(int units_Int,int scan_Range,int gains_Int,int reputation_Int,int clicks_Int,Dictionary<string,bool> upgrades_Purchased,Dictionary<string,bool> upgrades_Owned,Dictionary<string,bool> achievements_Earned){
units = units_Int;
scanRange = scan_Range;
gains = gains_Int;
reputation = reputation_Int;
clicks = clicks_Int;
upgradesPurchased = upgrades_Purchased;
upgradesOwned = upgrades_Owned;
achievementsEarned = achievements_Earned;
}
}
//Method that handles saving the object
public void SaveFile(){
string destination = Application.persistentDataPath + DATA_FILE;
FileStream file;
if (File.Exists (destination)) {
file = File.OpenWrite (destination);
} else {
file = File.Create (destination);
}
GameData data = new GameData (GameManager.Instance.units,GameManager.Instance.scanRange,GameManager.Instance.gains,GameManager.Instance.reputation,GameManager.Instance.clicks,UpgradeManager.Instance.upgradesPurchased,UpgradeManager.Instance.upgradesOwned,AchievementManager.Instance.achievementsEarned);
BinaryFormatter bf = new BinaryFormatter ();
bf.Serialize (file, data);
file.Close ();
NotificationsBar.Instance.ShowNotification ("Game saved success");
}
//Method that loads the object
public void LoadFile(){
string destination = Application.persistentDataPath + DATA_FILE;
FileStream file;
if (File.Exists (destination)) {
file = File.OpenRead (destination);
} else {
UpgradeManager.Instance.FirstLoad ();
return;
}
BinaryFormatter bf = new BinaryFormatter ();
GameData data = (GameData)bf.Deserialize (file);
file.Close ();
GameManager.Instance.units = data.units;
GameManager.Instance.scanRange = data.scanRange;
GameManager.Instance.gains = data.gains;
GameManager.Instance.reputation = data.reputation;
GameManager.Instance.clicks = data.clicks;
UpgradeManager.Instance.upgradesPurchased = data.upgradesPurchased;
UpgradeManager.Instance.upgradesOwned = data.upgradesOwned;
AchievementManager.Instance.achievementsEarned = data.achievementsEarned;
Debug.Log ("Units: " + data.units);
}
Theres a lot of code here but this is so everyone has a clear picture of what the entire system looks like
So the issue with this method is when adding a new value to the dictionary passed to GameData UpgradeManager.Instance.upgradesPurchased I will get an error when searching for data within the dictionary key not present in dictionary
My analysis is that due to the new value being added there is an offset in the dictionary from where the new value is placed and what used to be in that place
What I expected to happen when I first wrote out the code wa the dictionary would just autopopulate the new values and overwrite the old data
For a visual representation of what I mean lets say you have 2 upgrades
Upgrade1,Upgrade2
Now this is saved
Now the code changes and you have 3 upgrades
Upgrade1,Upgrade3,Upgrade2
What I assume would happen is the new value is just added into the save
So I am not exactly sure why this is happening....
Whilst I can't see the exact cause of the issue I would suggest the following:
First, take your save/load logic out of your GameData class and put it into a SaveDataManager class, that way you segregate responsibility.
From there, you can simplify your GameData class down to a struct making serialisation/desrialisation easier.
Then in your main game class whenever you have to load the game you can do something along the lines of:
SaveGameManger sgManager = new SaveGameManager(file);
gameData = sgManager.LoadGame()
This will make your code much easier to maintain and if this doesn't fix your problem it will be a lot easier to find.
Further to this, it will also allow you to build unit tests that verify the integrity of you load and save logic.
I've not had a chance to test it, but your separated and refactored code would look something like this (although it needs some validation checks added and whatnot):
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace temp
{
public class GameLoop
{
private SaveGameManager sgManager;
private GameData data;
private bool isPlaying;
public GameLoop()
{
sgManager = new SaveGameManager("MYSAVELOCATION");
data = sgManager.LoadGame();
isPlaying = true;
}
private void PlayGame()
{
while (isPlaying)
{
//All of your game code
}
}
}
public class SaveGameManager
{
private string saveFile;
private BinaryFormatter formatter;
public SaveGameManager(string file)
{
saveFile = file;
formatter = new BinaryFormatter();
}
public GameData LoadGame()
{
using (StreamReader reader = new StreamReader(saveFile))
{
return (GameData)formatter.Deserialize(reader.BaseStream);
}
}
public void SaveGame(GameData data)
{
using (StreamWriter writer = new StreamWriter(saveFile))
{
formatter.Serialize(writer.BaseStream, data);
}
}
}
[Serializable]
public struct GameData
{
public int units;
public int scanRange;
public int gains;
public int reputation;
public int clicks;
public Dictionary<string, bool> upgradesPurchased;
public Dictionary<string, bool> upgradesOwned;
public Dictionary<string, bool> achievementsEarned;
}
}
And I really would consider switching out your string keys for upgrades in favour of enums... Much less error prone.
I have a code-first Entity Framework class that looks like this:
public class Image
{
public int ImageID { get; set; }
public string DataType { get; set; }
public int Size { get; set; }
public byte[] Content { get; set; }
}
I have written several lines of code in a controller that receives a IFormFile and then extracts the file data and reads it into an Image:
var content = formFile.OpenReadStream();
byte[] buf = new byte[content.Length];
content.Read(buf, 0, buf.Length);
var newImg = new Image();
newImg.Content = buf;
newImg.DataType = formFile.ContentType;
Since this code is re-used wherever an image is being uploaded, I would like to somehow encapsulate it as a 'SaveUpload' function. It will be used in various controllers across the solution.
Is the best way to add this as a {set;} only non-mapped property to the Image class/table?
Or do I somehow encapsulate or inherit this property (sorry, I am still learning OOP terms)?
You may want to consider creating an UploadService class to encapsulate this logic. Neither the controller(s), nor the Image class should really be aware of these details and by abstracting it into a service you will likely find that the code is more readable and easier to maintain.
UploadService:
public class UploadService
{
public void SaveUpload(IFormFile formFile)
{
var content = formFile.OpenReadStream();
byte[] buf = new byte[content.Length];
content.Read(buf, 0, buf.Length);
var newImg = new Image();
newImg.Content = buf;
newImg.DataType = formFile.ContentType;
//insert newImg...
}
}
I would even consider taking it one step further by injecting this service into your controllers using a dependency injection framework like Unity or Ninject, which will allow you to isolate the service for unit testing.
You could do something like
public class Image
{
public int ImageID { get; set; }
public string DataType { get; set; }
public int Size { get; set; }
public byte[] Content { get; set;
public static Image SaveUpload(IFormFile formFile) {
var newImage = new Image();
var content = formFile.OpenReadStream();
byte[] buf = new byte[content.Length];
content.Read(buf, 0, buf.Length);
var newImg = new Image();
newImg.Content = buf;
newImg.DataType = formFile.ContentType;
return newImage;
}
}
Save with
var image = Image.SaveUpload(formFile);
Inside your class do next step:
public static void YourMethod(/*parameters, if you need them*/){
var content = formFile.OpenReadStream();
byte[] buf = new byte[content.Length];
content.Read(buf, 0, buf.Length);
var newImg = new Image();
newImg.Content = buf;
newImg.DataType = formFile.ContentType;
}
It's possible to add normal static function, but for good practic: POCO class should't have any logic expect fields. Better way is to create other class, f.e: UploadService which method: Save(Image image). Your choice.
I'm trying to XML serialize a class that contains two structs with the same name:
public class MyClass
{
public System.Windows.Size WSize = new System.Windows.Size();
public System.Drawing.Size DSize = new Size.Drawing.Size();
}
The resulting error:
Types 'System.Drawing.Size' and 'System.Windows.Size' both use the XML type name,
'Size', from namespace ''. Use XML attributes to specify a unique XML name and/or
namespace for the type.
Everything I've found so far involves decorating the Type with an XML attribute. I can't directly decorate either struct since they are not my code.
I feel like I'm missing something easy here...Is there an XML attribute that I can apply to the fields?
EDIT
I've added answer using a couple surrogate properties. I'm not happy with that particular implementation since it leaves public properties hanging out.
I've also considered DataContractSerialization but I'm hesitant to take that next step quite yet. Anyone else have something they can suggest?
EDIT 2
There may have been some confusion in my wording. I can modify and decorate MyClass, WSize and DSize. However, perhaps obviously, I cannot modify System.Windows.Size or System.Drawing.Size.
You can do it by proxy with custom XML serialization, I created this fully working example, although there is a lot of error checking to be done its a place to start.
public class MyClass
{
public System.Windows.Size WSize = new System.Windows.Size();
public System.Drawing.Size DSize = new System.Drawing.Size();
}
public class MyClassProxy : MyClass, IXmlSerializable
{
public new System.Windows.Size WSize { get { return base.WSize; } set { base.WSize = value; } }
public new System.Drawing.Size DSize { get { return base.DSize; } set { base.DSize = value; } }
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
reader.MoveToContent();
reader.ReadStartElement();
string wheight = reader["height"];
string wwidth = reader["width"];
int w, h;
w = int.Parse(wwidth);
h = int.Parse(wheight);
WSize = new Size(w, h);
reader.ReadStartElement();
string dheight = reader["height"];
string dwidth = reader["width"];
w = int.Parse(dwidth);
h = int.Parse(dheight);
DSize = new System.Drawing.Size(w, h);
}
public void WriteXml(System.Xml.XmlWriter writer)
{
writer.WriteStartElement("MyClassProxy");
writer.WriteStartElement("WSize");
writer.WriteAttributeString("height", WSize.Height.ToString());
writer.WriteAttributeString("width", WSize.Width.ToString());
writer.WriteEndElement();
writer.WriteStartElement("DSize");
writer.WriteAttributeString("height", DSize.Height.ToString());
writer.WriteAttributeString("width", DSize.Width.ToString());
writer.WriteEndElement();
writer.WriteEndElement();
}
}
class Program
{
static void Main(string[] args)
{
MyClassProxy p = new MyClassProxy();
p.DSize = new System.Drawing.Size(100, 100);
p.WSize = new Size(400, 400);
string xml = "";
using (StringWriter sw = new StringWriter())
{
System.Xml.XmlWriter wr = System.Xml.XmlWriter.Create(sw);
p.WriteXml(wr);
wr.Close();
xml = sw.ToString();
}
MyClassProxy p2 = new MyClassProxy();
using (StringReader sr = new StringReader(xml))
{
System.Xml.XmlReader r = System.Xml.XmlReader.Create(sr);
p2.ReadXml(r);
}
MyClass baseClass = (MyClass)p2;
Print(baseClass);
Console.ReadKey();
}
static void Print(MyClass c)
{
Console.WriteLine(c.DSize.ToString());
Console.WriteLine(c.WSize.ToString());
}
}
Here's a possibility that I'm not terribly happy with (not very clean):
public class MyClass
{
public System.Windows.Size WSize = new System.Windows.Size();
[XmlIgnore]
public System.Drawing.Size DSize = new Size();
public int DSizeWidthForSerialization
{
get
{
return DSize.Width;
}
set
{
DSize.Width = value;
}
}
public int DSizeHeightForSerialization
{
get
{
return DSize.Height;
}
set
{
DSize.Height = value;
}
}
}
I ended up creating a new class to house System.Drawing.Size. Within that new class I created implicit operators and handled some of the constructors. This allowed me to serialize and not have to change any existing code:
public class MyClass
{
public System.Windows.Size WSize = new System.Windows.Size();
public MyDrawingSize DSize = new System.Drawing.Size();
public class MyDrawingSize
{
public int Height, Width;
public MyDrawingSize() { } //Needed for deserialization
public MyDrawingSize(int width, int height)
{
Width = width;
Height = height;
}
public static implicit operator System.Drawing.Size(MyDrawingSize size)
{
return new System.Drawing.Size(size.Width, size.Height);
}
public static implicit operator MyDrawingSize(System.Drawing.Size size)
{
return new MyDrawingSize() { Width = size.Width, Height = size.Height };
}
}
}
I am trying to store a list of objects I created in the isolated storage and be able to display them in a list by auto generating a title for them. So far the code works but once I tombstone the app and start it up all my data is saved except for the list of objects. I think my problem may be with how I initialize the list in the first place, or possibly how I am displaying the names. Any help is appreciated.
this code is in my App.xaml.cs:
public partial class App : Application
{
public List<my_type> testList = new List<my_type>();
void loadvalues()
{
IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
List<my_Type> L;
if (settings.TryGetValue<List<DrinkSesh>>("Storage", out L))
{ testList = L; }
}
void savevalues()
{
IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
settings["Storage"] = testList;
settings.Save();
}
}
This code is on my mainPage to add the items to the list:
(Application.Current as App).testList.Add(new my_type());
and this code is to implement the titles onto the screen on a different page:
public different_class()
{
{
InitializeComponent();
for (i = 0; i < (Application.Current as App).testList.Count; i++)
{
CreateATextBlock((Application.Current as App).testList[i].Title_ToString(), i);
}
}
private void CreateATextBlock(String title,int num)
{
testblockname = new TextBlock();
testblockname.Text = (num + 1) + ". " + title;
DrList.Children.Add(testblockname);
}
}
Thank you in advance!
Here is the code I use to save and load lists of objects from isolated storage.
public class IsoStoreHelper
{
private static IsolatedStorageFile _isoStore;
public static IsolatedStorageFile IsoStore
{
get { return _isoStore ?? (_isoStore = IsolatedStorageFile.GetUserStoreForApplication()); }
}
public static void SaveList<T>(string folderName, string dataName, ObservableCollection<T> dataList) where T : class
{
if (!IsoStore.DirectoryExists(folderName))
{
IsoStore.CreateDirectory(folderName);
}
string fileStreamName = string.Format("{0}\\{1}.dat", folderName, dataName);
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileStreamName, FileMode.Create, IsoStore))
{
DataContractSerializer dcs = new DataContractSerializer(typeof(ObservableCollection<T>));
dcs.WriteObject(stream, dataList);
}
}
public static ObservableCollection<T> LoadList<T>(string folderName, string dataName) where T : class
{
ObservableCollection<T> retval = new ObservableCollection<T>();
if (!IsoStore.DirectoryExists(folderName))
{
IsoStore.CreateDirectory(folderName);
}
string fileStreamName = string.Format("{0}\\{1}.dat", folderName, dataName);
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileStreamName, FileMode.OpenOrCreate, IsoStore))
{
if (stream.Length > 0)
{
DataContractSerializer dcs = new DataContractSerializer(typeof(ObservableCollection<T>));
retval = dcs.ReadObject(stream) as ObservableCollection<T>;
}
}
return retval;
}
}
By simply adding your collection (List) to your IsolatedStorageSettings you are relying on the built in serializer (the DataContractSerializer) to serialize your object for persisting to disk.
Are you sure your object can be correctly serialized and deserialized?
Doing this yourself is probably the easiest way to do this.
If you do this yourself, not that:
- DataContractSerializer is slow
- DataContractJsonSerializer is faster
- Json.net is faster still
- Binary serialization is fastest.
When serializing yourself you should also save in an IsolatedStorageFile rahter than in the settings. This can help with performance and also adds flexibility which can aid debugging and testing.