Saving and Loading a List - c#

I'm working on a project where I have this list
List<Vara> minaVaror = new List<Vara>();
It's created from this class:
class Vara
{
public double streckKod { get; set; }
public string artNamn { get; set; }
}
And this is how I add items to the list:
minaVaror.Add(new Vara() {streckKod = inputBox1, artNamn = textBox2.Text });
Alright so this list is going to be added items to every now and then so I need to be able to save and load the content/items of the list so you won't lose the data when the program is closed and reopened.
We did something like this in class last year where we saved the data over to an XML file with XmlSerializer however that was only for 1 int, I'm not really sure how to do it for a whole list.

By definition, XmlSerializer cannot deserialize a List<T> or an ArrayList. From MSDN.
The XmlSerializer cannot deserialize the following: arrays of ArrayList and arrays of List<T>.
So you can serialize a List<T>, but you cannot deserialize List<T>.
So you can use this code to serialize in XML and deserialize an XML file.
namespace DataContractSerializerExample
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
// You must apply a DataContractAttribute or SerializableAttribute
// to a class to have it serialized by the DataContractSerializer.
[DataContract(Name = "Vara", Namespace = "http://www.contoso.com")]
public class Vara
{
[DataMember()]
public double streckKod { get; set; }
[DataMember]
public string artNamn { get; set; }
}
public sealed class Test
{
private Test() { }
public static void Main()
{
List<Vara> minaVaror = new List<Vara>() { new Vara() { streckKod = 5.0, artNamn = "test1" }, new Vara() { streckKod = 5.0, artNamn = "test2" }, new Vara() { streckKod = 5.0, artNamn = "test3" } };
string fileName = "test.xml";
Serialize<List<Vara>>(fileName, minaVaror);
List<Vara> listDes = Deserialize<List<Vara>>(fileName);
}
public static void Serialize<T>(string fileName, T obj)
{
FileStream writer = new FileStream(fileName, FileMode.Create);
DataContractSerializer ser =
new DataContractSerializer(typeof(T));
ser.WriteObject(writer, obj);
writer.Close();
}
public static T Deserialize<T>(string fileName)
{
FileStream fs = new FileStream(fileName,
FileMode.Open);
XmlDictionaryReader reader =
XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
DataContractSerializer ser = new DataContractSerializer(typeof(T));
T des =
(T)ser.ReadObject(reader, true);
reader.Close();
fs.Close();
return des;
}
}
}
Note: You should add a reference to the C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0\System.Runtime.Serialization.dll.

Related

Parse empty field to XML

i am parsing class with empty string in some element in XML file like below.
objectCxml.Request.InvoiceDetailRequest.InvoiceDetailRequestHeader.InvoiceDetailHeaderIndicator = "";
XmlSerializer s = new XmlSerializer(typeof(cXML));
XmlTextWriter tw = new XmlTextWriter(path, Encoding.UTF8);
s.Serialize(tw, objectCxml);
It generate xml like below
<InvoiceDetailHeaderIndicator xsi:type="xsd:string"/>
But i want it as below
<InvoiceDetailHeaderIndicator/>
Any Suggestion?
InvoiceDetailHeaderIndicator property is object
So... don't do that? Make it string and you should be set.
Ultimately, the point here is that XmlSerializer wants to be able to round-trip data reliably; that is its job. There are two ways of doing that:
know the type statically (i.e. string instead of object in the type model)
embed additional metadata in the payload (xsi:type="xsd:string")
If you don't want 2, you'll need 1, otherwise it can't work. Frankly 1 is a much better idea anyway.
I tested with a local minimal setup, and this worked fine:
public class InvoiceHeaderThing
{
public string InvoiceDetailHeaderIndicator { get; set; }
}
Full code below:
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
static class P
{
static void Main()
{
const string path = "my.xml";
var objectCxml = new cXML();
objectCxml.Request.InvoiceDetailRequest.InvoiceDetailRequestHeader.InvoiceDetailHeaderIndicator = "";
XmlSerializer s = new XmlSerializer(typeof(cXML));
using (XmlTextWriter tw = new XmlTextWriter(path, Encoding.UTF8))
{
s.Serialize(tw, objectCxml);
}
Console.WriteLine(File.ReadAllText(path));
}
}
public class cXML
{
public RequestThing Request { get; set; } = new RequestThing();
}
public class RequestThing
{
public InvoiceDetailThing InvoiceDetailRequest { get; set; } = new InvoiceDetailThing();
}
public class InvoiceDetailThing
{
public InvoiceHeaderThing InvoiceDetailRequestHeader { get; set; } = new InvoiceHeaderThing();
}
public class InvoiceHeaderThing
{
public string InvoiceDetailHeaderIndicator { get; set; }
}

C# deserialize xml array of different types into multiple arrays

I have the following xml:
<Applications>
<AccessibleApplication></AccessibleApplication>
<AccessibleApplication></AccessibleApplication>
<EligibleApplication></EligibleApplication>
<EligibleApplication></EligibleApplication>
</Applications>
Is there a way to deserialize this into a C# object so that the AccessibleApplications and EligibleApplications are two separate arrays? I tried the following but get an exception because "Applications" is used more than once.
[XmlArray("Applications")]
[XmlArrayItem("AccessibleApplication")]
public List<Application> AccessibleApplications { get; set; }
[XmlArray("Applications")]
[XmlArrayItem("EligibleApplication")]
public List<Application> EligibleApplications { get; set; }
The exception is:
The XML element 'Applications' from namespace '' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.
Is this possible to do?
Thanks!
Edit: I forgot to mention that I do not want to have an "Applications" class just for the sake of providing a container object for the two arrays. I have several situations like this and I don't want the clutter of these classes whose only purpose is to split up two arrays of the same type.
I was hoping to be able to deserialize the two arrays into an outer object using some sort of tag like [XmlArrayItem="Application/AccessibleApplication"] without creating an "Applications" class.
I've found a fairly neat way to do this, first make a class like this:
using System.Xml.Serialization;
[XmlRoot]
public class Applications
{
[XmlElement]
public string[] AccessibleApplication;
[XmlElement]
public string[] EligibleApplication;
}
Notice how the elements are individual arrays. Now using this class (I had my XML in a separate file hence the XmlDocument class).
var doc = new XmlDocument();
doc.Load("../../Apps.xml");
var serializer = new XmlSerializer(typeof(Applications));
Applications result;
using (TextReader reader = new StringReader(doc.InnerXml))
{
result = (Applications)serializer.Deserialize(reader);
}
Now to prove this works you can write this all in to a console app and do a foreach to print all the values in your arrays, like so:
foreach (var app in result.AccessibleApplication)
{
Console.WriteLine(app);
}
foreach (var app in result.EligibleApplication)
{
Console.WriteLine(app);
}
You can use XmlElement attribute to deserialize to different lists:
public class Applications
{
[XmlElement("AccessibleApplication")]
public List<Application> AccessibleApplications { get; set; }
[XmlElement("EligibleApplication")]
public List<Application> EligibleApplications { get; set; }
}
public class Application
{
[XmlText]
public string Value { get; set; }
}
So for a sample XML:
<Applications>
<AccessibleApplication>xyz</AccessibleApplication>
<AccessibleApplication>abc</AccessibleApplication>
<EligibleApplication>def</EligibleApplication>
<EligibleApplication>zzz</EligibleApplication>
</Applications>
The following snippet would output the below:
using (var reader = new StreamReader("XMLFile1.xml"))
{
var serializer = new XmlSerializer(typeof(Applications));
var applications = (Applications)serializer.Deserialize(reader);
Console.WriteLine("AccessibleApplications:");
foreach (var app in applications.AccessibleApplications)
{
Console.WriteLine(app.Value);
}
Console.WriteLine();
Console.WriteLine("EligibleApplications:");
foreach (var app in applications.EligibleApplications)
{
Console.WriteLine(app.Value);
}
}
Output:
AccessibleApplications:
xyz
abc
EligibleApplications:
def
zzz
You can use this class to create objects from strings, creating strings from objects and create byte [] from objects
StringToObject
var applicationObject = new XmlSerializerHelper<Applications>().StringToObject(xmlString);
ObjectToString
var xmlString = new XmlSerializerHelper<Applications>().ObjectToString(applicationObject);
ObjectToByteArray
var byteArray = new XmlSerializerHelper<Applications>().ObjectToByteArray(applicationObject);
The XmlSerializerHelper:
namespace StackOverflow
{
public class XmlSerializerHelper<T> where T : class
{
private readonly XmlSerializer _serializer;
public XmlSerializerHelper()
{
_serializer = new XmlSerializer(typeof(T));
}
public T ToObject(string xml)
{
return (T)_serializer.Deserialize(new StringReader(xml));
}
public string ToString(T obj, string encoding)
{
using (var memoryStream = new MemoryStream())
{
_serializer.Serialize(memoryStream, obj);
return Encoding.GetEncoding(encoding).GetString(memoryStream.ToArray());
}
}
public byte[] ToByteArray(T obj, Encoding encoding = null)
{
var settings = GetSettings(encoding);
using (var memoryStream = new MemoryStream())
{
using (var writer = XmlWriter.Create(memoryStream, settings))
{
_serializer.Serialize(writer, obj);
}
return memoryStream.ToArray();
}
}
private XmlWriterSettings GetSettings(Encoding encoding)
{
return new XmlWriterSettings
{
Encoding = encoding ?? Encoding.GetEncoding("ISO-8859-1"),
Indent = true,
IndentChars = "\t",
NewLineChars = Environment.NewLine,
ConformanceLevel = ConformanceLevel.Document
};
}
}
}
Your Class:
[XmlRoot]
public class Applications
{
[XmlElement("AccessibleApplication")]
public string[] AccessibleApplication { get; set; }
[XmlElement("EligibleApplication")]
public string[] EligibleApplication { get; set; }
}
Or
[XmlRoot]
public class Applications
{
[XmlElement("AccessibleApplication")]
public List<string> AccessibleApplication { get; set; }
[XmlElement("EligibleApplication")]
public List<string> EligibleApplication { get; set; }
}
Cheers.

Saving a generic list

Is there a way to save a list to disk generically? I tried data contract serializer, but it always generates an empty list.
public static List<T> Load<T>() where T : class,new()
{
var serializer = new DataContractSerializer(typeof(List<T>));
string path = HttpContext.Current.Server.MapPath("~/App_Data/" + typeof(T).ToString() + ".xml");
if (!System.IO.File.Exists(path))
{
return new List<T>();
}
else
{
using (var s = new System.IO.FileStream(path, System.IO.FileMode.Open))
{
return serializer.ReadObject(s) as List<T>;
}
}
}
public static void Save<T>(List<T> data) where T : class,new()
{
var serializer = new DataContractSerializer(typeof(List<T>));
Enumerate<T>(data);
string path = HttpContext.Current.Server.MapPath("~/App_Data/" + typeof(T).ToString() + ".xml");
using (var s = new System.IO.FileStream(path, System.IO.FileMode.Create))
{
serializer.WriteObject(s, data);
}
}
You might want to use JavaScriptSerializer
var json = new JavaScriptSerializer().Serialize(thing);
JSON lists are generic.
UPDATE: Ass claimed by TimS Json.NET is better serializer so if adding 3rd party library is an option here is an article on how to do it.
What about a binary serializer
public static void SerializeToBin(object obj, string filename)
{
Directory.CreateDirectory(Path.GetDirectoryName(filename));
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
using (FileStream fs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
bf.Serialize(fs, obj);
}
}
public static T DeSerializeFromBin<T>(string filename) where T : new()
{
if (File.Exists(filename))
{
T ret = new T();
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
ret = (T)bf.Deserialize(fs);
}
return ret;
}
else
throw new FileNotFoundException(string.Format("file {0} does not exist", filename));
}
Based on what you're trying to do, the key might also be your class T, ensuring that it is decorated with the proper [DataContract] and [DataMember] attributes. Here is a working example based on your code in question (however if you don't care to be able to utilize the persisted file outside of your code, you might find better performance in the binary serializer):
[DataContract]
public class Mydata
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
List<Mydata> myData = new List<Mydata>();
myData.Add(new Mydata() { Id = 1, Name = "Object 1" });
myData.Add(new Mydata() { Id = 2, Name = "Object 2" });
string path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + #"\" + typeof(Mydata).ToString() + ".xml";
Save<Mydata>(myData, path);
List<Mydata> myNewData = Load<Mydata>(path);
Console.WriteLine(myNewData.Count);
Console.ReadLine();
}
public static List<T> Load<T>(string filename) where T : class
{
var serializer = new DataContractSerializer(typeof(List<T>));
if (!System.IO.File.Exists(filename))
{
return new List<T>();
}
else
{
using (var s = new System.IO.FileStream(filename, System.IO.FileMode.Open))
{
return serializer.ReadObject(s) as List<T>;
}
}
}
public static void Save<T>(List<T> list, string filename)
{
var serializer = new DataContractSerializer(typeof(List<T>));
using (FileStream fs = new FileStream(filename, FileMode.Create))
{
using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(fs))
{
serializer.WriteObject(writer, list);
}
}
}
}

PaymentDetails is not successfully deserialized, returning a null object, because it seems it is expected to have IXmlDeserializable

[XmlRoot("Quote")]
public class Quote
{
[XmlElement("Insurance")]
public InsuranceDetails InsDetails { get; set; }
[XmlElement("Payment")]
public PaymentDetails PayDetails { get; set; }
}
public class InsuranceDetails : IXmlSerializable
{
[XmlElement(ElementName = "Details1")]
public string Details1 { get; set; }
public void ReadXml(XmlReader reader)
{
reader.ReadStartElement("Insurance");
Details1 = reader.ReadElementString("Details1");
reader.ReadEndElement();
}
public void WriteXml(XmlWriter writer)
{
// do write suff
}
}
public class PaymentDetails
{
[XmlElement(ElementName = "Details1")]
public string Details1 { get; set; }
}
Given this example, using XmlSerializer to deserialize my string to QuoteObject, PaymentDetails is not successfully deserialized, returning a null object, because it seems it is expected to have IXmlDeserializable. It only works if PaymentDetails is parsed in first place. Is this some expected behavior from XmlSerializer?
using (TextReader read = new StringReader(xml))
{
var serializer = new XmlSerializer(typeof(Quote));
return (Quote)serializer.Deserialize(read);
}
Well these are the ReadXml and WriteXml I modified:
public void ReadXml(XmlReader reader)
{
reader.MoveToContent();
var empty=reader.IsEmptyElement;
reader.ReadStartElement();
if(!empty){
Details1=reader.ReadElementString("Details1");
reader.ReadEndElement();
}
}
public void WriteXml(XmlWriter writer)
{
var str=string.IsNullOrWhiteSpace(Details1)?"":Details1;
writer.WriteElementString("Details1",str);
}
Following are serialize and deserialize functions:
public static string Serialize<T>(T t)
{
var xmlser=new XmlSerializer(typeof(T));
XmlWriterSettings settings = new XmlWriterSettings();
using(StringWriter textWriter = new StringWriter()) {
using(XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings)) {
xmlser.Serialize(xmlWriter, t);
}
return textWriter.ToString();
}
}
public static T Deserialize<T>(string xml)
{
if(string.IsNullOrEmpty(xml)) {
return default(T);
}
XmlSerializer serializer = new XmlSerializer(typeof(T));
XmlReaderSettings settings = new XmlReaderSettings();
using(StringReader textReader = new StringReader(xml)) {
using(XmlReader xmlReader = XmlReader.Create(textReader, settings)) {
return (T) serializer.Deserialize(xmlReader);
}
}
}
Serialization Test:
var q=new Quote();
q.PayDetails = new PaymentDetails{Details1="Payment Details 1"};
q.InsDetails=new InsuranceDetails{Details1="Insurance Details 1"};
str = Serialize<Quote>(q);
Which gives (str):
<?xml version="1.0" encoding="utf-16"?>
<Quote xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Payment>
<Details1>Payment Details 1</Details1>
</Payment>
<Insurance>
<Details1>Insurance Details 1</Details1>
</Insurance>
</Quote>
Deserialization Test:
var dq=Deserialize<Quote>(str);
Console.WriteLine(dq.PaymentDetails.Detail1);//gives "Payment Details 1"
Console.WriteLine(dq.InsuranceDetails.Detail1);//gives "Insurance Details 1"
PS:- The Serialize code was copied from another SO answer verbatim. I learned how to serialize to string using StringWriter.
First of all you don't have to implement IXmlSerializable in any of the classes. Second of all, you don't provide the content of the xml variable. It may contain a mistype/bug, if you created it manually.
I used the following code, to test your classes:
using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace XmlDeSerialize
{
[XmlRoot("Quote")]
public class Quote
{
[XmlElement("Insurance")]
public InsuranceDetails InsDetails { get; set; }
[XmlElement("Payment")]
public PaymentDetails PayDetails { get; set; }
}
public class InsuranceDetails
{
[XmlElement(ElementName = "Details1")]
public string Details1 { get; set; }
}
public class PaymentDetails
{
[XmlElement(ElementName = "Details1")]
public string Details1 { get; set; }
}
class Program
{
static void Main(string[] args)
{
var qin = new Quote
{
InsDetails = new InsuranceDetails { Details1 = "insurance details text" },
PayDetails = new PaymentDetails { Details1 = "payment details text" },
};
string xml;
using (var stream = new MemoryStream())
{
var serializer = new XmlSerializer(typeof(Quote));
serializer.Serialize(stream, qin);
stream.Position = 0;
using (var sr = new StreamReader(stream))
{
xml = sr.ReadToEnd();
}
}
Quote qout;
using (TextReader read = new StringReader(xml))
{
var deserializer = new XmlSerializer(typeof(Quote));
var obj = deserializer.Deserialize(read);
qout = (Quote)obj;
}
Console.WriteLine("InsDetails.Details1='{0}'", qout.InsDetails.Details1);
Console.WriteLine("PayDetails.Details1='{0}'", qout.PayDetails.Details1);
}
}
}
The value of xml after serialization:
<?xml version="1.0"?>
<Quote xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Insurance>
<Details1>insurance details text</Details1>
</Insurance>
<Payment>
<Details1>payment details text</Details1>
</Payment>
</Quote>
The console output I received:
InsDetails.Details1='insurance details text'
PayDetails.Details1='payment details text'
Try the code yourself and see if it works for you. Clearly to me you don't provide valid XML content for deserialization, or other part of your code you did not provide in your question is to blame.

How can I serialize an object with a Dictionary<string,object> property?

In the example code below, I get this error:
Element
TestSerializeDictionary123.Customer.CustomProperties
vom Typ
System.Collections.Generic.Dictionary`2[[System.String,
mscorlib, Version=2.0.0.0,
Culture=neutral,
PublicKeyToken=b77a5c561934e089],[System.Object,
mscorlib, Version=2.0.0.0,
Culture=neutral,
PublicKeyToken=b77a5c561934e089]] can
not be serialized because it
implements IDictionary.
When I take out the Dictionary property, it works fine.
How can I serialize this Customer object with the dictionary property? Or what replacement type for Dictionary can I use that would be serializable?
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
using System.Text;
namespace TestSerializeDictionary123
{
public class Program
{
static void Main(string[] args)
{
List<Customer> customers = Customer.GetCustomers();
Console.WriteLine("--- Serializing ------------------");
foreach (var customer in customers)
{
Console.WriteLine("Serializing " + customer.GetFullName() + "...");
string xml = XmlHelpers.SerializeObject<Customer>(customer);
Console.WriteLine(xml);
Console.WriteLine("Deserializing ...");
Customer customer2 = XmlHelpers.DeserializeObject<Customer>(xml);
Console.WriteLine(customer2.GetFullName());
Console.WriteLine("---");
}
Console.ReadLine();
}
}
public static class StringHelpers
{
public static String UTF8ByteArrayToString(Byte[] characters)
{
UTF8Encoding encoding = new UTF8Encoding();
String constructedString = encoding.GetString(characters);
return (constructedString);
}
public static Byte[] StringToUTF8ByteArray(String pXmlString)
{
UTF8Encoding encoding = new UTF8Encoding();
Byte[] byteArray = encoding.GetBytes(pXmlString);
return byteArray;
}
}
public static class XmlHelpers
{
public static string SerializeObject<T>(object o)
{
MemoryStream ms = new MemoryStream();
XmlSerializer xs = new XmlSerializer(typeof(T));
XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.UTF8);
xs.Serialize(xtw, o);
ms = (MemoryStream)xtw.BaseStream;
return StringHelpers.UTF8ByteArrayToString(ms.ToArray());
}
public static T DeserializeObject<T>(string xml)
{
XmlSerializer xs = new XmlSerializer(typeof(T));
MemoryStream ms = new MemoryStream(StringHelpers.StringToUTF8ByteArray(xml));
XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.UTF8);
return (T)xs.Deserialize(ms);
}
}
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Street { get; set; }
public string Location { get; set; }
public string ZipCode { get; set; }
public Dictionary<string,object> CustomProperties { get; set; }
private int internalValue = 23;
public static List<Customer> GetCustomers()
{
List<Customer> customers = new List<Customer>();
customers.Add(new Customer { Id = 1, FirstName = "Jim", LastName = "Jones", ZipCode = "23434" });
customers.Add(new Customer { Id = 2, FirstName = "Joe", LastName = "Adams", ZipCode = "12312" });
customers.Add(new Customer { Id = 3, FirstName = "Jack", LastName = "Johnson", ZipCode = "23111" });
customers.Add(new Customer { Id = 4, FirstName = "Angie", LastName = "Reckar", ZipCode = "54343" });
customers.Add(new Customer { Id = 5, FirstName = "Henry", LastName = "Anderson", ZipCode = "16623" });
return customers;
}
public string GetFullName()
{
return FirstName + " " + LastName + "(" + internalValue + ")";
}
}
}
In our application we ended up using:
DataContractSerializer xs = new DataContractSerializer(typeof (T));
instead of:
XmlSerializer xs = new XmlSerializer(typeof (T));
which solved the problem as DatacontractSerializer supports Dictionary.
Another solution is ths XML Serializable Generic Dictionary workaround also works in the above example, and there is a long discussion at that link from people using it, might be useful for people working with this issue.
Here's a generic dictionary class that knows how to serialize itself:
public class XmlDictionary<T, V> : Dictionary<T, V>, IXmlSerializable {
[XmlType("Entry")]
public struct Entry {
public Entry(T key, V value) : this() { Key = key; Value = value; }
[XmlElement("Key")]
public T Key { get; set; }
[XmlElement("Value")]
public V Value { get; set; }
}
System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema() {
return null;
}
void IXmlSerializable.ReadXml(System.Xml.XmlReader reader) {
this.Clear();
var serializer = new XmlSerializer(typeof(List<Entry>));
reader.Read(); // Why is this necessary?
var list = (List<Entry>)serializer.Deserialize(reader);
foreach (var entry in list) this.Add(entry.Key, entry.Value);
reader.ReadEndElement();
}
void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer) {
var list = new List<Entry>(this.Count);
foreach (var entry in this) list.Add(new Entry(entry.Key, entry.Value));
XmlSerializer serializer = new XmlSerializer(list.GetType());
serializer.Serialize(writer, list);
}
}
You can't (short of doing it all yourself, which is horrible); the xml serializer isn't going to have a clue what to do with object, as it doesn't include type metadata in the wire format. One (hacky) option would be to stream these all as strings for the purposes of serialization, but then you have a lot of extra parsing (etc) code to write.
You can use Binary serialization instead. (Just make sure all your classes are marked as [Serializable]. Of course, it won't be in XML format, but you didn't list that as a requirement :)
I've just found this blog post by Rakesh Rajan which describes one possible solution:
Override XmlSerialization by making the type implement the System.Xml.Serialization.IXmlSerializable class. Define how you want the object to be serialized in XML in the WriteXml method, and define how you could recreate the object from an xml string in the ReadXml method.
But this wouldn't work as your Dictionary contains an object rather than a specific type.
What about to mark Customer class as DataContract and its properties as DataMembers. DataContract serializer will do the serialization for you.
Try Serializating through BinaryFormatter
private void Deserialize()
{
try
{
var f_fileStream = File.OpenRead(#"dictionarySerialized.xml");
var f_binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
myDictionary = (Dictionary<string, myClass>)f_binaryFormatter.Deserialize(f_fileStream);
f_fileStream.Close();
}
catch (Exception ex)
{
;
}
}
private void Serialize()
{
try
{
var f_fileStream = new FileStream(#"dictionarySerialized.xml", FileMode.Create, FileAccess.Write);
var f_binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
f_binaryFormatter.Serialize(f_fileStream, myDictionary);
f_fileStream.Close();
}
catch (Exception ex)
{
;
}
}

Categories