Getting the CS1501 error "No overload for method 'Load' takes '1' arguments" and it is driving me insane because I have looked for a solution all over internet but cannot find any. So I ask here now, and hopefully recieve a solution that works.
PPSerialization:
using UnityEngine;
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
public class PPSerialization {
public static BinaryFormatter binaryFormatter = new BinaryFormatter();
public static void Save(string saveTag, object obj) {
MemoryStream memoryStream = new MemoryStream();
binaryFormatter.Serialize(memoryStream, obj);
string temp = System.Convert.ToBase64String(memoryStream.ToArray());
PlayerPrefs.SetString(saveTag, temp);
}
public static object Load(string saveTag, object obj) {
string temp = PlayerPrefs.GetString(saveTag);
if (temp == string.Empty) {
return null;
}
MemoryStream memoryStream = new MemoryStream(System.Convert.FromBase64String(temp));
return binaryFormatter.Deserialize(memoryStream);
}
}
GameInformation:
using UnityEngine;
using System.Collections;
public class GameInformation : MonoBehaviour {
void Awake() {
DontDestroyOnLoad(transform.gameObject);
}
public static BaseEquipment EquipmentOne { get; set; }
public static string PlayerName { get; set; }
public static BaseCharacterClass PlayerClass { get; set; }
public static int PlayerLevel { get; set; }
public static int Health { get; set; }
public static int Stamina { get; set; }
public static int Strength { get; set; }
public static int Intelligence { get; set; }
}
Save_Info:
using UnityEngine;
using System.Collections;
public class Save_Info
{
public static void SaveAllInfo() {
PlayerPrefs.SetString("PLAYERNAME", GameInformation.PlayerName);
PlayerPrefs.SetInt("PLAYERLEVEL", GameInformation.PlayerLevel);
PlayerPrefs.SetInt("HEALTH", GameInformation.Health);
PlayerPrefs.SetInt("STAMINA", GameInformation.Stamina);
PlayerPrefs.SetInt("STRENGTH", GameInformation.Strength);
PlayerPrefs.SetInt("INTELLIGENCE", GameInformation.Intelligence);
if (GameInformation.EquipmentOne != null)
{
PPSerialization.Save("EQUIPMENTITEM1", GameInformation.EquipmentOne);
}
Debug.Log("SAVED");
}
}
Load_Info:
using UnityEngine;
using System.Collections;
public class Load_Info
{
public static void LoadAllInfo()
{
GameInformation.PlayerName = PlayerPrefs.GetString("PLAYERNAME");
GameInformation.PlayerLevel = PlayerPrefs.GetInt("PLAYERLEVEL");
GameInformation.Health = PlayerPrefs.GetInt("HEALTH");
GameInformation.Stamina = PlayerPrefs.GetInt("STAMINA");
GameInformation.Strength = PlayerPrefs.GetInt("STRENGTH");
GameInformation.Intelligence = PlayerPrefs.GetInt("INTELLIGENCE");
if (PlayerPrefs.GetString("EQUIPMENTITEM1") != null)
{
GameInformation.EquipmentOne = (BaseEquipment)PPSerialization.Load("EQUIPMENTITEM1");
}
}
}
You have method Load with 2 parameters
public static object Load(string saveTag, object obj) {
string temp = PlayerPrefs.GetString(saveTag);
if (temp == string.Empty) {
return null;
}
But you try to call it only with 1 paramert
GameInformation.EquipmentOne = (BaseEquipment)PPSerialization.Load("EQUIPMENTITEM1");
Change your Load method like this :
public static object Load(string saveTag) {
string temp = PlayerPrefs.GetString(saveTag);
if (temp == string.Empty) {
return null;
}
MemoryStream memoryStream = new MemoryStream(System.Convert.FromBase64String(temp));
return binaryFormatter.Deserialize(memoryStream);
}
Related
I have a unity project with an error in six different files all with the same error:
the type or namespace name 'IAotStubbable' could not be found.
I, for the life of me, cannot find the issue.
Here are the different files:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Unity.VisualScripting
{
[AddComponentMenu("Visual Scripting/Variables")]
[DisableAnnotation]
[IncludeInSettings(false)]
public class Variables : LudiqBehaviour, IAotStubbable
{
[Serialize, Inspectable]
public VariableDeclarations declarations { get; internal set; } =
new VariableDeclarations() { Kind = VariableKind.Object };
public static VariableDeclarations Graph(GraphPointer pointer)
{
Ensure.That(nameof(pointer)).IsNotNull(pointer);
if (pointer.hasData)
{
return GraphInstance(pointer);
}
else
{
return GraphDefinition(pointer);
}
}
public static VariableDeclarations GraphInstance(GraphPointer pointer)
{
return pointer.GetGraphData<IGraphDataWithVariables>().variables;
}
public static VariableDeclarations GraphDefinition(GraphPointer pointer)
{
return GraphDefinition((IGraphWithVariables)pointer.graph);
}
public static VariableDeclarations GraphDefinition(IGraphWithVariables graph)
{
return graph.variables;
}
public static VariableDeclarations Object(GameObject go) => go.GetOrAddComponent<Variables>().declarations;
public static VariableDeclarations Object(Component component) => Object(component.gameObject);
public static VariableDeclarations Scene(Scene? scene) => SceneVariables.For(scene);
public static VariableDeclarations Scene(GameObject go) => Scene(go.scene);
public static VariableDeclarations Scene(Component component) => Scene(component.gameObject);
public static VariableDeclarations ActiveScene => Scene(SceneManager.GetActiveScene());
public static VariableDeclarations Application => ApplicationVariables.current;
public static VariableDeclarations Saved => SavedVariables.current;
public static bool ExistOnObject(GameObject go) => go.GetComponent<Variables>() != null;
public static bool ExistOnObject(Component component) => ExistOnObject(component.gameObject);
public static bool ExistInScene(Scene? scene) => scene != null && SceneVariables.InstantiatedIn(scene.Value);
public static bool ExistInActiveScene => ExistInScene(SceneManager.GetActiveScene());
[ContextMenu("Show Data...")]
protected override void ShowData()
{
base.ShowData();
}
public IEnumerable<object> GetAotStubs(HashSet<object> visited)
{
// Include the constructors for AOT serialization
// https://support.ludiq.io/communities/5/topics/3952-x
foreach (var declaration in declarations)
{
var defaultConstructor = declaration.value?.GetType().GetPublicDefaultConstructor();
if (defaultConstructor != null)
{
yield return defaultConstructor;
}
}
}
}
}
using System;
namespace Unity.VisualScripting
{
public interface IGraphNest : IAotStubbable
{
IGraphNester nester { get; set; }
GraphSource source { get; set; }
IGraph embed { get; set; }
IMacro macro { get; set; }
IGraph graph { get; }
Type graphType { get; }
Type macroType { get; }
bool hasBackgroundEmbed { get; }
}
}
namespace Unity.VisualScripting
{
public interface IMacro : IGraphRoot, ISerializationDependency, IAotStubbable
{
IGraph graph { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace Unity.VisualScripting
{
public interface IGraphElement : IGraphItem, INotifiedCollectionItem, IDisposable, IPrewarmable, IAotStubbable, IIdentifiable, IAnalyticsIdentifiable
{
new IGraph graph { get; set; }
bool HandleDependencies();
int dependencyOrder { get; }
new Guid guid { get; set; }
void Instantiate(GraphReference instance);
void Uninstantiate(GraphReference instance);
IEnumerable<ISerializationDependency> deserializationDependencies { get; }
}
}
using System;
using UnityEngine;
namespace Unity.VisualScripting
{
public interface IGraph : IDisposable, IPrewarmable, IAotStubbable, ISerializationDepender
{
Vector2 pan { get; set; }
float zoom { get; set; }
MergedGraphElementCollection elements { get; }
string title { get; }
string summary { get; }
IGraphData CreateData();
IGraphDebugData CreateDebugData();
void Instantiate(GraphReference instance);
void Uninstantiate(GraphReference instance);
}
}
using UnityEngine;
namespace Unity.VisualScripting
{
public interface IMachine : IGraphRoot, IGraphNester, IAotStubbable
{
IGraphData graphData { get; set; }
GameObject threadSafeGameObject { get; }
}
}
What can I do to fix this? I've surfed forums for help for a while but havent found anything yet. This is for a massive school project and I would really love to have it finished. Thank you for any and all responses.
I have a class that contains Range[] as property and Range class is a self referencing class. I used [JsonIgnore] to prevent StackoverflowException but it works for only Serialize not Deserialize. How can I fix this?
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
namespace testoverflow
{
class Program
{
public static void Main(string[] args)
{
GlobalVariable.Json = "[{\"TotalBytesReceived\":0,\"Id\":\"b03750fb291a46708f8e1a7409553075\",\"NofThread\":8,\"Speed\":0,\"Progress\":0.0,\"FilePath\":\"C:\\\\Users\\\\kafeinaltor\\\\Downloads\",\"RangeDir\":\"C:\\\\Users\\\\kafeinaltor\\\\AppData\\\\Roaming\",\"Url\":\"http://ipv4.download.thinkbroadband.com/20MB.zip\",\"Ranges\":[{\"Start\":0,\"End\":9223372036854775806,\"TotalBytesReceived\":0,\"IsDownloaded\":false,\"FileId\":\"87cd7715dc0740c1b82ddd681bf2523d\",\"Size\":9223372036854775807,\"Status\":4,\"IsIdle\":false,\"SaveDir\":\"C:\\\\Users\\\\kafeinaltor\\\\AppData\\\\Roaming\",\"FilePath\":\"C:\\\\Users\\\\kafeinaltor\\\\AppData\\\\Roaming\\\\87cd7715dc0740c1b82ddd681bf2523d\",\"Md5Checksum\":null}],\"Info\":null,\"DownloadRequestMessage\":null}]";
var a = new MTDO();
Console.WriteLine(GlobalVariable.Json);
Console.ReadKey(true);
}
public static class GlobalVariable
{
public static string Json { get; set; }
}
public class MTDO
{
public MTDO()
{
Ranges = new Range[]
{
new Range(0L, 100L, ""),
new Range(101L, 200L, "")
};
Id = Guid.NewGuid().ToString("N");
Reminder.AddOrUpdate(this);
}
public string Id { get; set; }
public Range[] Ranges{ get; set; }
}
public class Range
{
public long Start { get; set; }
public long End { get; set; }
public string SaveDir { get; set; }
public long TotalBytesReceived{ get; set; }
public Range(long start, long end, string saveDir)
{
this.Start = start;
this.End = end;
this.SaveDir = Guid.NewGuid().ToString();
}
[JsonIgnore]
public Range Remaining
{
get
{
return new Range(Start + TotalBytesReceived, End, SaveDir);
}
}
}
public class Reminder
{
public Reminder()
{
}
public static void AddOrUpdate(MTDO mtdo)
{
var list = JsonConvert.DeserializeObject<List<MTDO>>(Read());
if (list == null)
list = new List<MTDO>();
var exists = list.Any(x => x.Id == mtdo.Id);
if (!exists)
list.Add(mtdo);
else
{
var i = list.Select((x, j) => new {val = x, index = j})
.First(x => x.val.Id == mtdo.Id).index;
list[i] = mtdo;
}
WriteJson(list);
}
public static List<MTDO> ReadList()
{
var list = JsonConvert.DeserializeObject<List<MTDO>>(Read());
if (list == null)
list = new List<MTDO>();
return list;
}
static string Read()
{
try
{
return GlobalVariable.Json;
}
catch
{
return "";
}
}
static void WriteJson(List<MTDO> list)
{
GlobalVariable.Json = JsonConvert.SerializeObject(list);
}
}
}
}
UPDATE: I have updated myquestion adding minimum reproducable code in Console Application. You can copy/paste and run directly.
The problem is that you have an infinite recursion:
You call MTDO constructor
Inside MTDO constructor you call Reminder.AddOrUpdate(this);
Inside that method you have var list = JsonConvert.DeserializeObject<List<MTDO>>(Read());
Which calls MTDO constructor again (step 1)
These steps keep repeating until you get StackOverflowException.
I have the following class I want to serialise:
public class UpdateDoorCommand : IXmlSerializable
{
// string such as D1
public string DoorId { get; }
public string Name { get; }
public string Notes { get; }
public UpdateDoorCommand(string doorId, string name, string notes)
{
DoorId = doorId;
Name = name;
Notes = notes;
}
public UpdateDoorCommand()
{
}
public XmlSchema GetSchema()
{
throw new NotImplementedException();
}
public void ReadXml(XmlReader reader)
{
throw new NotImplementedException();
}
public void WriteXml(XmlWriter writer)
{
writer.WriteStartElement("Door");
writer.WriteAttributeString("Address", "D1");
writer.WriteElementString("Name", Name);
writer.WriteElementString("Notes", Notes);
writer.WriteEndElement();
}
}
I want the output to look like this:
<Door Address="D1">
<Name>Name1</Name>
<Notes>Notes1</Notes>
</Door>
I use the following code to serialise the object:
[TestMethod]
public async Task XmlSerialisationTest()
{
var model = new UpdateDoorCommand("D1", "Name1", "Notes1");
var mediaTypeFormatters = new MediaTypeFormatterCollection();
mediaTypeFormatters.XmlFormatter.UseXmlSerializer = true;
mediaTypeFormatters.XmlFormatter.WriterSettings.OmitXmlDeclaration = true;
var content = new ObjectContent<UpdateDoorCommand>(model, mediaTypeFormatters.XmlFormatter);
// this does not look like the type
var str = await content.ReadAsStringAsync();
}
}
However the the output of the serialisation does not give the desired results.
The xml is wrapped in an element with the classname of the object.
How can I get desired xml output using the ObjectContent class?
Note that the code needs a reference to System.Net.Http.Formatting in order to run.
I'm not sure if the two ways are compatible but try this:
[XmlRoot(ElementName = "Door", DataType = "string")]
public class UpdateDoorCommand : IXmlSerializable
{
// *snip*
public void WriteXml(XmlWriter writer)
{
//writer.WriteStartElement("Door");
writer.WriteAttributeString("Address", "D1");
writer.WriteElementString("Name", Name);
writer.WriteElementString("Notes", Notes);
//writer.WriteEndElement();
}
}
Simple with Xml Linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
UpdateDoorCommand updateDoorCommand = new UpdateDoorCommand("D1","Name1","Note1");
updateDoorCommand.WriteXml();
}
}
public class UpdateDoorCommand
{
// string such as D1
public string DoorId { get; set; }
public string Name { get; set; }
public string Notes { get; set; }
public UpdateDoorCommand(string doorId, string name, string notes)
{
DoorId = doorId;
Name = name;
Notes = notes;
}
public UpdateDoorCommand()
{
}
public void ReadXml(XmlReader reader)
{
throw new NotImplementedException();
}
public void WriteXml()
{
XElement doorCommand = new XElement("Door", new object[] {
new XAttribute("Address", DoorId),
new XElement("Name", Name),
new XElement("Notes1", Notes)
});
}
}
}
Here is my code -
class Appointments:IAppointments
{
private readonly IList<IAppointment> _list = new List<IAppointment>();
public Appointments()
{
}
public bool Load()
{
throw new NotImplementedException();
}
public bool Save()
{
throw new NotImplementedException();
}
public IEnumerable<IAppointment> GetAppointmentsOnDate(DateTime date)
{
throw new NotImplementedException();
}
public int IndexOf(IAppointment item)
{
return _list.IndexOf(item);
}
public void Insert(int index, IAppointment item)
{
_list.Insert(index, item);
}
public void RemoveAt(int index)
{
_list.RemoveAt(index);
}
public IAppointment this[int index]
{
get
{
return _list[index];
}
set
{
_list[index] = value;
}
}
public void Add(IAppointment item)
{
_list.Add(item);
}
public void Clear()
{
_list.Clear();
}
public bool Contains(IAppointment item)
{
return _list.Contains(item);
}
public void CopyTo(IAppointment[] array, int arrayIndex)
{
_list.CopyTo(array, arrayIndex);
}
public int Count
{
get { return _list.Count; }
}
public bool IsReadOnly
{
get { return _list.IsReadOnly; }
}
public bool Remove(IAppointment item)
{
return _list.Remove(item);
}
public IEnumerator<IAppointment> GetEnumerator()
{
return _list.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
foreach (IAppointment item in _list)
{
if (item == null)
{
break;
}
yield return item;
}
I would like help on how to do the load and save methods. The save method needs to save to a text file. The load method needs to load from a txt file.
IAppointment interface -
namespace Calendar
{
public interface IAppointment
{
DateTime Start { get; }
int Length { get; }
string DisplayableDescription { get; }
bool OccursOnDate(DateTime date);
}
}
The website is complaining that this is mostly code so I am going to write this pointless sentence until it hopefully goes away. Thank you for your patience.
This is the serialization code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace Calendar
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
//add to appointments to object below
Appointments appointments = new Appointments()
{
appointments = new List<Appointment>() {
new Appointment(){ start = DateTime.Today, length = 2, displayableDescription = "Meeting wiith Joe", occursOnDate = true},
new Appointment(){ start = DateTime.Today.AddDays(2), length = 3, displayableDescription = "Meeting wiith Jane", occursOnDate = false}
}
};
//use this code for writing
XmlSerializer serializer = new XmlSerializer(typeof(Appointments));
StreamWriter writer = new StreamWriter(FILENAME);
serializer.Serialize(writer, appointments);
writer.Flush();
writer.Close();
writer.Dispose();
//use this code for reading
XmlSerializer xs = new XmlSerializer(typeof(Appointments));
XmlTextReader reader = new XmlTextReader(FILENAME);
Appointments newAppointments = (Appointments)xs.Deserialize(reader);
}
}
[XmlRoot("appointments")]
public class Appointments
{
[XmlElement("appointment")]
public List<Appointment> appointments { get; set; }
}
[XmlRoot("appointment")]
public class Appointment
{
[XmlElement("start")]
public DateTime start { get; set; }
[XmlElement("length")]
public int length { get; set; }
[XmlElement("displayableDescription")]
public string displayableDescription { get; set; }
[XmlElement("occursOnDate")]
public bool occursOnDate { get; set; }
}
}
I would just use Json as it's much cleaner and smaller than XML. So for example:
private IList<IAppointment> _list {get; set;}
public Appointments()
{
_list = Load() ?? new List<IAppointment>();
}
public List<IAppointment> Load()
{
try
{
var json = File.ReadAllText(".Appointments.json");
var list = JsonConvert.DeserializeObject<List<IAppointment>>(json);
return list;
}
catch
{
return null;
}
}
public bool Save()
{
try
{
var json = JsonConvert.SerializeObject(_list);
File.WriteAllText(".Appointments.json",json);
return true;
}
catch
{
return false;
}
}
Don't forget to add Newtonsoft.Json to your project via Nuget:
To install Json.NET, run the following command in the Package Manager Console
PM> Install-Package Newtonsoft.Json -Version 6.0.8
I combined my code into your classes. Will need to be debugged but should help you understand serialization better.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace Calendar
{
class Program
{
static void Main(string[] args)
{
}
}
public class IAppointments : IAppointment
{
public DateTime Start { get; set; }
public int Length { get; set; }
public string DisplayableDescription { get; set; }
public bool OccursOnDate(DateTime date)
{
return true;
}
}
class Appointments : IAppointments
{
const string FILENAME = #"c:\temp\test.xml";
private readonly IList<IAppointment> _list = new List<IAppointment>();
public void Add(IAppointment item)
{
_list.Add(item);
}
public bool Load()
{
XmlSerializer xs = new XmlSerializer(typeof(c_Appointments));
XmlTextReader reader = new XmlTextReader(FILENAME);
c_Appointments newAppointments = (c_Appointments)xs.Deserialize(reader);
foreach (Appointment appointment in newAppointments.appointments)
{
IAppointments newAppointment = new IAppointments();
newAppointment.Start = appointment.start;
newAppointment.Length = appointment.length;
newAppointment.DisplayableDescription = appointment.displayableDescription;
this.Add(newAppointment);
}
return true;
}
public bool Save()
{
c_Appointments appointments = new c_Appointments();
appointments.appointments = new List<Appointment>();
foreach (IAppointment iAppointment in _list)
{
Appointment newAppoint = new Appointment();
appointments.appointments.Add(newAppoint);
newAppoint = (Appointment)iAppointment;
}
XmlSerializer serializer = new XmlSerializer(typeof(c_Appointments));
StreamWriter writer = new StreamWriter(FILENAME);
serializer.Serialize(writer, appointments);
writer.Flush();
writer.Close();
writer.Dispose();
return true;
}
}
public interface IAppointment
{
DateTime Start { get; }
int Length { get; }
string DisplayableDescription { get; }
bool OccursOnDate(DateTime date);
}
[XmlRoot("appointments")]
public class c_Appointments
{
[XmlElement("appointment")]
public List<Appointment> appointments { get; set; }
}
[XmlRoot("appointment")]
public class Appointment
{
[XmlElement("start")]
public DateTime start { get; set; }
[XmlElement("length")]
public int length { get; set; }
[XmlElement("displayableDescription")]
public string displayableDescription { get; set; }
}
}
In .Net 4 or 4.5, how would you design a serializable class that contains an instance of one class from a set of classes? For instance, suppose I have a Garage class, which can hold an instance of any "vehicle" type classes, say Car, Boat, Motorcycle, Motorhome. But the Garage can only hold an instance of one of those classes. I have tried a few different ways of doing this, but my problem is to make it serializable.
Here is a starting example where there is only one option for the instance in the Garage class. You should be able to plug it right into a new console app and try it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace Patterns
{
[Serializable()]
public class Garage
{
private Vehicle _MyVehicle;
public Garage()
{
}
public string GarageOwner { get; set; }
public Vehicle MyVehicle
{
get { return _MyVehicle; }
set { _MyVehicle = value; }
}
}
[Serializable()]
public class Vehicle
{
public string VehicleType { get; set; }
public int VehicleNumber { get; set; }
}
class Serializer
{
static string _StartupPath = #"C:\Projects\Patterns\Data\";
static string _StartupFile = "SerializerTest.xml";
static string _StartupXML = _StartupPath + _StartupFile;
static void Main(string[] args)
{
Console.Write("Press w for write. Press r for read:");
ConsoleKeyInfo cki = Console.ReadKey(true);
Console.WriteLine("Pressed: " + cki.KeyChar.ToString());
if (cki.KeyChar.ToString() == "w")
{
Garage MyGarage = new Garage();
MyGarage.GarageOwner = "John";
MyGarage.MyVehicle = new Vehicle();
MyGarage.MyVehicle.VehicleType = "Car";
MyGarage.MyVehicle.VehicleNumber = 1234;
WriteGarageXML(MyGarage);
Console.WriteLine("Serialized");
}
else if (cki.KeyChar.ToString() == "r")
{
Garage MyGarage = ReadGarageXML();
Console.WriteLine("Deserialized Garage owned by " + MyGarage.GarageOwner);
}
Console.ReadKey();
}
public static void WriteGarageXML(Garage pInstance)
{
XmlSerializer writer = new XmlSerializer(typeof(Garage));
using (FileStream file = File.OpenWrite(_StartupXML))
{
writer.Serialize(file, pInstance);
}
}
public static Garage ReadGarageXML()
{
XmlSerializer reader = new XmlSerializer(typeof(Garage));
using (FileStream input = File.OpenRead(_StartupXML))
{
return reader.Deserialize(input) as Garage;
}
}
}
}
Based on another SO article, this is what finally worked for me.
It can serialize and deserialize cleanly. Using this example, I can design a "tree" of objects which have options for what is used. So this could be extended that a Car can have one Engine of several different Engine type classes and one Interior of several different Interior types... and so on.
The code began to work by adding the statements below like: [XmlInclude(typeof(Car))]
But please let me know if there are better ways!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace Patterns
{
public class Garage
{
private Vehicle _MyVehicle;
public Garage()
{
}
public string GarageOwner { get; set; }
public Vehicle MyVehicle
{
get { return _MyVehicle; }
set { _MyVehicle = value; }
}
}
[XmlInclude(typeof(Car))]
[XmlInclude(typeof(Boat))]
[XmlInclude(typeof(Motorcycle))]
[XmlInclude(typeof(Motorhome))]
public abstract class Vehicle
{
public string VehicleType { get; set; }
public int VehicleNumber { get; set; }
}
public class Car : Vehicle
{
public int Doors { get; set; }
}
public class Boat : Vehicle
{
public int Engines { get; set; }
}
public class Motorcycle : Vehicle
{
public int Wheels { get; set; }
}
public class Motorhome : Vehicle
{
public int Length { get; set; }
}
class Serializer
{
static string _StartupPath = #"C:\Projects\Patterns\Data\";
static string _StartupFile = "SerializerTest.xml";
static string _StartupXML = _StartupPath + _StartupFile;
static void Main(string[] args)
{
Console.Write("Press w for write. Press r for read:");
ConsoleKeyInfo cki = Console.ReadKey(true);
Console.WriteLine("Pressed: " + cki.KeyChar.ToString());
if (cki.KeyChar.ToString() == "w")
{
Garage MyGarage = new Garage();
MyGarage.GarageOwner = "John";
Car c = new Car();
c.VehicleType = "Lexus";
c.VehicleNumber = 1234;
c.Doors = 4;
MyGarage.MyVehicle = c;
WriteGarageXML(MyGarage);
Console.WriteLine("Serialized");
}
else if (cki.KeyChar.ToString() == "r")
{
Garage MyGarage = ReadGarageXML();
Console.WriteLine("Deserialized Garage owned by " + MyGarage.GarageOwner);
}
Console.ReadKey();
}
public static void WriteGarageXML(Garage pInstance)
{
XmlSerializer writer = new XmlSerializer(typeof(Garage));
using (FileStream file = File.OpenWrite(_StartupXML))
{
writer.Serialize(file, pInstance);
}
}
public static Garage ReadGarageXML()
{
XmlSerializer reader = new XmlSerializer(typeof(Garage));
using (FileStream input = File.OpenRead(_StartupXML))
{
return reader.Deserialize(input) as Garage;
}
}
}
}
To serialize sequences of serializable classes you can use Generic list instances.
I generated this
<?xml version="1.0"?>
<Garage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GarageOwner>John</GarageOwner>
<MyVehicles>
<Vehicle>
<VehicleType>Car</VehicleType>
<VehicleNumber>1234</VehicleNumber>
</Vehicle>
<Vehicle>
<VehicleType>Boat</VehicleType>
<VehicleNumber>56234</VehicleNumber>
</Vehicle>
</MyVehicles>
</Garage>
By simply converting the MyVehicle to a generic list
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
namespace Patterns
{
[Serializable()]
public class Garage
{
public string GarageOwner { get; set; }
public List<Vehicle> MyVehicles { get; set; }
}
[Serializable()]
public class Vehicle
{
public string VehicleType { get; set; }
public int VehicleNumber { get; set; }
}
class Serializer
{
static string _StartupPath = #"C:\temp\";
static string _StartupFile = "SerializerTest.xml";
static string _StartupXML = _StartupPath + _StartupFile;
static void Main(string[] args)
{
Console.Write("Press w for write. Press r for read:");
ConsoleKeyInfo cki = Console.ReadKey(true);
Console.WriteLine("Pressed: " + cki.KeyChar.ToString());
if (cki.KeyChar.ToString() == "w")
{
Garage MyGarage = new Garage();
MyGarage.GarageOwner = "John";
// Create some vehicles
var myVehicle1 = new Vehicle();
myVehicle1.VehicleType = "Car";
myVehicle1.VehicleNumber = 1234;
var myVehicle2 = new Vehicle();
myVehicle2.VehicleType = "Boat";
myVehicle2.VehicleNumber = 56234;
// Create a new instance and add the vehicles
MyGarage.MyVehicles = new List<Vehicle>()
{
myVehicle1,
myVehicle2
};
WriteGarageXML(MyGarage);
Console.WriteLine("Serialized");
}
else if (cki.KeyChar.ToString() == "r")
{
Garage MyGarage = ReadGarageXML();
Console.WriteLine("Deserialized Garage owned by " + MyGarage.GarageOwner);
}
Console.ReadKey();
}
public static void WriteGarageXML(Garage pInstance)
{
XmlSerializer writer = new XmlSerializer(typeof(Garage));
using (FileStream file = File.OpenWrite(_StartupXML))
{
writer.Serialize(file, pInstance);
}
}
public static Garage ReadGarageXML()
{
XmlSerializer reader = new XmlSerializer(typeof(Garage));
using (FileStream input = File.OpenRead(_StartupXML))
{
return reader.Deserialize(input) as Garage;
}
}
}
}