I know that protobuf-net doesn't support a jagged array and a wrapper is a workaround. I've tried to test it, serialization works fine, but deserialization does nothing, i.e. no error, after deserialization the objects are empty.
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Source
{
public Source()
{
List = new List<Dictionary<string, Item>>();
}
[ProtoIgnore]
public List<Dictionary<string, Item>> List { get; set; }
public List<DictionaryWrapper<string, Item>> ListProto
{
get
{
return List.ConvertAll(x => new DictionaryWrapper<string, Item>(x));
}
set
{
List = value.ConvertAll(x => x.Dictionary);
}
}
}
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Item
{
public string Value { get; set; }
}
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public sealed class DictionaryWrapper<TKey, TValue>
{
public DictionaryWrapper()
{
}
public DictionaryWrapper(Dictionary<TKey, TValue> value)
{
Dictionary = value;
}
public Dictionary<TKey, TValue> Dictionary { get; set; }
}
serialization method
public void Test()
{
byte[] data = null;
try
{
var source = new Source();
for (var i = 0; i < 5; i++)
{
source.List.Add(new Dictionary<string, Item> {{i.ToString(), new Item {Value = i.ToString()}}});
}
using (var stream = new MemoryStream())
{
Serializer.Serialize(stream, source);
data = stream.ToArray();
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Source result;
using (var stream = new MemoryStream(data))
{
result = Serializer.Deserialize<Source>(stream);
}
Console.WriteLine(result.List.Count);
}
UPDATE: I've found a workaround. So this fixes the deserialization, still, don't know why ListProto set was not called.
[ProtoBeforeSerialization]
public void ProtoBeforeSerialization()
{
List1Proto = List1.ConvertAll(x => new DictionaryWrapper<string, Item>(x));
}
[ProtoAfterDeserialization]
public void ProtoAfterDeserialization()
{
List1 = List1Proto.ConvertAll(x => x.Dictionary);
}
Related
I have a class that inherits from List<T> and add one more class property
public class DrivenList : List<int>
{
public string Name {get;set;}
private DrivenList() { }
public DrivenList(string name) { this.Nname = name; }
}
When JSON serializing the object using Newtonsoft.Json, I get only the list item. ( [1,2,3] )
Any ideas how to add the Name property to the results?
Solved: by adding this attribute to the list
[JsonObject(MemberSerialization = MemberSerialization.Fields)]
public class DrivenList : List<int>
As far as I know with Newtonsoft all you can do is something like this:
[JsonObject(MemberSerialization = MemberSerialization.Fields)]
public class DrivenList : List<int>
{
[JsonProperty]
public string Name { get; set; }
private DrivenList() { }
public DrivenList(string name) { this.Name = name; }
}
But this will add you unwanted (maybe) fields.
Personally I will do composition instead of inheritance:
public class DrivenList
{
public string Name { get; set; }
public List<int> Items { get; set; }
private DrivenList() { }
public DrivenList(string name) { this.Name = name; }
}
What .NET version are you using and what serializer?
If you are using the standard serializer, then adding [DataMember] annotations would be the answer.
https://msdn.microsoft.com/en-us/library/bb412179(v=vs.110).aspx
But I would suggest to use Json.NET http://www.newtonsoft.com/json
Update:
I would suggest not to directly inherit to List
class Program
{
static void Main(string[] args)
{
var list = new Driven("Ragnarok");
list.Items.Add(1);
list.Items.Add(2);
string json = JsonConvert.SerializeObject(list);
Console.WriteLine(json);
Console.ReadKey();
}
}
public class Driven
{
public Driven(string name)
{
this.Name = name;
}
public List<int> Items { get; set; } = new List<int>();
public string Name { get; set; }
}
Output:
{"Items":[1,2],"Name":"Ragnarok"}
An alternative solution could be to delegate the implementation of IList to your own property. Then you can use the DataContractSerializer. The upside of this is that all the existing C#-code (and all your tests) will still be intact, and no custom logic is needed for serializing it.
If that's not an option and you really want to use NewtonSoft, then you should take a look at this answer, and create your own JsonConverter.
How to serialize/deserialize a custom collection with additional properties using Json.Net
The problem is the following: when an object implements IEnumerable,
JSON.net identifies it as an array of values and serializes it
following the array Json syntax (that does not include properties)
Here's an example that use DataContractSerializer:
JsonHelper from CodeProject
public class JsonHelper
{
/// <summary>
/// JSON Serialization
/// </summary>
public static string JsonSerializer<T>(T t)
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
MemoryStream ms = new MemoryStream();
ser.WriteObject(ms, t);
string jsonString = Encoding.UTF8.GetString(ms.ToArray());
ms.Close();
return jsonString;
}
/// <summary>
/// JSON Deserialization
/// </summary>
public static T JsonDeserialize<T>(string jsonString)
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
T obj = (T)ser.ReadObject(ms);
return obj;
}
}
And the new implementation of your class.
[DataContract]
public class DrivenList : IList<int>
{
[DataMember]
public List<int> Items = new List<int>();
[DataMember]
public string Name { get; set; }
private DrivenList() { }
public DrivenList(string name) { this.Name = name; }
#region Implementation of IList
public IEnumerator<int> GetEnumerator()
{
return Items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)Items).GetEnumerator();
}
public void Add(int item)
{
Items.Add(item);
}
public void Clear()
{
Items.Clear();
}
public bool Contains(int item)
{
return Items.Contains(item);
}
public void CopyTo(int[] array, int arrayIndex)
{
Items.CopyTo(array, arrayIndex);
}
public bool Remove(int item)
{
return Items.Remove(item);
}
public int Count
{
get { return Items.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public int IndexOf(int item)
{
return Items.IndexOf(item);
}
public void Insert(int index, int item)
{
Items.Insert(index, item);
}
public void RemoveAt(int index)
{
Items.RemoveAt(index);
}
public int this[int index]
{
get { return Items[index]; }
set { Items[index] = value; }
}
#endregion
}
And an example usage:
var list = new DrivenList("foo");
list.Add(1);
list.Add(3);
list.Add(5);
var json = JsonHelper.JsonSerializer(list);
Output:
{"Items":[1,3,5],"Name":"foo"}
Apply the DataContract attribute for the class and DataMember attribute for the properties.
[DataContract]
public class DrivenList : List<int>
{
[DataMember]
public string Name {get;set;}
private DrivenList() { }
public DrivenList(string name) { this.Nname = name; }
}
Since the BinaryFormatter is giving me trouble serializing a Dictionary on Ios I decided to switch to protobuf-net. And use that to serialize stuff in my Unity3d game. Here is some code:
This is the class that hold all the data:
using System;
using System.Collections.Generic;
using ProtoBuf;
using UnityEngine;
namespace SerializationLib
{
[ProtoContract]
public class GameData
{
[ProtoMember(1)]
public int _coinAmount ;
[ProtoMember(2)]
public int _upgradeLevel;
[ProtoMember(3)]
public Level_Data[] _level_Data;
[ProtoMember(4)]
public CharacterUpgradeList _charUpgradeList;
[ProtoMember(5)]
public SerialVector2 serialVector;
}
[ProtoContract]
public class CharacterUpgradeList
{
private List<UpgradeData>[] upgData;
[ProtoMember(1,OverwriteList = true)]
public Dictionary<string, List<UpgradeData>> upgradeList;
public CharacterUpgradeList()
{
upgData = new List<UpgradeData>[4];
for (int i = 0; i < upgData.Length; i++)
{
upgData[i] = new List<UpgradeData> {
new UpgradeData(),
new UpgradeData(),
new UpgradeData(),
new UpgradeData(),
new UpgradeData(),
new UpgradeData()
};
}
upgradeList = new Dictionary<string, List<UpgradeData>>
{
{"Man",upgData[0]},
{"Woman",upgData[1]},
{"Boy",upgData[2]},
{"Girl",upgData[3]}
};
}
}
[ProtoContract]
public class Level_Data
{
[ProtoMember(1)]
public int completion_status;
[ProtoMember(2)]
public int star_Rating;
}
[ProtoContract]
public class UpgradeData
{
[ProtoMember(1)]
public bool lockStatus;
[ProtoMember(2)]
public bool purchased;
}
[ProtoContract]
public struct SerialVector2
{
[ProtoMember(1)]
public float x;
[ProtoMember(2)]
public float y;
public SerialVector2(Vector2 vect)
{
x = vect.x;
y = vect.y;
}
public Vector2 returnVector2()
{
return new Vector2(x, y);
}
}
}
This is the data serializer that I'm using
using System;
using System.Collections.Generic;
using SerializationLib;
using ProtoBuf.Meta;
namespace DataSerializer
{
class Program
{
static void Main(string[] args)
{
var Model = TypeModel.Create();
Model.Add(typeof(GameData), true);
Model.Add(typeof(CharacterUpgradeList), true);
Model.Add(typeof(Level_Data), true);
Model.Add(typeof(UpgradeData), true);
Model.Add(typeof(SerialVector2), true);
Model.AllowParseableTypes = true;
Model.AutoAddMissingTypes = true;
Model.Compile("DataSerializer", "DataSerializer.dll");
}
}
}
this is a protobuf wraper to use in my other c# scripts in unity
using UnityEngine;
using System.IO;
public static class ProtoWraper {
private static DataSerializer m_serialiezer = new DataSerializer();
public static T LoadObjectFromResources<T>(string resourcePath)
{
TextAsset objectAsset = Resources.Load(resourcePath, typeof(TextAsset)) as TextAsset;
if (objectAsset == null)
{
return default(T);
}
T deserializedObject = default(T);
using (MemoryStream m = new MemoryStream(objectAsset.bytes))
{
deserializedObject = (T)m_serialiezer.Deserialize(m, null, typeof(T));
}
return deserializedObject;
}
public static T LoadObjectFromPath<T>(string path)
{
if (!File.Exists(path))
{
return default(T);
}
T deserializedObject = default(T);
using(FileStream f = new FileStream(path,FileMode.Open))
{
deserializedObject = (T)m_serialiezer.Deserialize(f,null,typeof(T));
}
return deserializedObject;
}
public static void SaveObjectToPath<T>(string objectPath, string filename, T serializedObject)
{
if (!Directory.Exists(objectPath))
{
Directory.CreateDirectory(objectPath);
}
using (FileStream f = new FileStream(objectPath + filename, FileMode.OpenOrCreate))
{
m_serialiezer.Serialize(f, serializedObject);
}
}
}
now the problem is when I call data = ProtoWraper.LoadObjectFromPath<GameData>(filename); I get ArgumentException: An element with the same key already exists in the dictionary.
Nevermind, I was being a complete moron and not re-compiling the data serializer after changes to Serializationlib :D. It's all good now.
We have some code that makes a copy of a List<T> of objects. The problem is the code is returning a readonly array of T[] instead of a List<T>.
Why is that, and how can I fix this deserialization code?
public interface ITestObject { }
[KnownType(typeof(ITestObject))]
[DataContract(Name = "TestObject")]
public class TestObject : ITestObject
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Value { get; set; }
}
public class TestApp
{
public void Run()
{
IList<ITestObject> a = new List<ITestObject>();
a.Add(new TestObject() { Id = 1, Value = "A" });
a.Add(new TestObject() { Id = 2, Value = "B" });
IList<ITestObject> b = Copy(a);
// a is a List<T> while b is a readonly T[]
Debug.WriteLine(a.GetType().FullName);
Debug.WriteLine(b.GetType().FullName);
}
public IList<ITestObject> Copy(IList<ITestObject> list)
{
DataContractSerializer serializer = new DataContractSerializer(typeof(IList<ITestObject>), new Type[] { typeof(TestObject) });
using (Stream stream = new MemoryStream())
{
serializer.WriteObject(stream, list);
stream.Seek(0, SeekOrigin.Begin);
IList<ITestObject> clone = (IList<ITestObject>)serializer.ReadObject(stream);
stream.Close();
return clone;
}
}
}
I'm guessing it's something to do with the fact List<T> isn't listed as a KnownType
Try using a DataContractSerializer(typeof(List<ITestObject>) so that it knows the concrete type
I have an issue with the .NET XML Serializer where I have do different XML Elements with different names that map to the same type. Basically, the objects should be exactly the same, but I want them to have a string or enum or something that identifies which of the three possible element names were used. So here's an example:
<Body>
<MyTypeA>
<Foo>bar</Foo>
</MyTypeA>
<MyTypeB>
<Foo>bar</Foo>
</MyTypeB>
</Body>
Now, for the classes, MyTypeA and MyTypeB will both be the same type. For example:
public class Body {
public MyType MyTypeA { get; set; }
public MyType MyTypeB { get; set; }
}
public class MyType {
public string Foo { get; set; }
[XmlIgnore]
public MyTypeType { get; set; }
}
public enum MyTypeType
{
MyTypeA,
MyTypeB
}
When serializing it works fine, because I can always just ensure one way or another that the enum is set properly before serializing. But when deserializing it is not getting set and I'm not sure there's a way how.
For the record, I unfortunately don't get to set the schema, otherwise I would have built it in such a way that I didn't have this problem.
If i understood your question correctly, this might help you. Just write you XML file path on the 4th line and try it.
namespace ConsoleApplication1
{
class Program
{
//private const string xmlPath = #"C:\Users\Jumast\Desktop\StackOverflowQuestion.xml";
private const string xmlPath, // put the file path here
static Body makeBody()
{
var instance1 = new MyType() { Category = Category.MyTypeA, Foo = "bar" };
var instance2 = new MyType() { Category = Category.MyTypeB, Foo = "bar" };
return new Body(){Instance1 = instance1, Instance2 = instance2};
}
static void serializeBody(Body body, string path)
{
var ser = new DataContractSerializer(body.GetType(), body.GetType().Name, "");
using (var w = XmlWriter.Create(path, new XmlWriterSettings() { Indent = true }))
{
ser.WriteObject(w, body);
}
}
static Body deseerializeBody(string xmlPath)
{
Body deserializedBody;
var ser = new XmlSerializer(typeof(Body));
using (Stream stream = File.OpenRead(xmlPath))
{
deserializedBody = (Body)ser.Deserialize(stream);
}
return deserializedBody;
}
static void writeBodyToConsole(Body body)
{
Console.WriteLine("Instance1: " + body.Instance1);
Console.WriteLine("Instance2: " + body.Instance2);
Console.ReadKey();
}
static void Main(string[] args)
{
serializeBody(makeBody(), xmlPath);
writeBodyToConsole(deseerializeBody(xmlPath));
}
}
public class Body : IXmlSerializable
{
#region Properties
public MyType Instance1 { get; set; }
public MyType Instance2 { get; set; }
#endregion
#region IXmlSerializable
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
reader.ReadStartElement();
Instance1 = new MyType(reader);
Instance2 = new MyType(reader);
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
Instance1.WriteXml(writer);
Instance2.WriteXml(writer);
}
#endregion
}
public class MyType : IXmlSerializable
{
#region Fields
private Category _category;
#endregion
#region Constructors
public MyType()
{
_category = Category.nil;
Foo = string.Empty;
}
public MyType(XmlReader reader) { ReadXml(reader);}
#endregion
#region Methods
public override string ToString()
{
var sb = new StringBuilder();
sb.Append(string.Format("Foo = {0}", Foo));
sb.Append(" , ");
sb.Append(string.Format("Category = {0}", Category));
return sb.ToString();
}
#endregion
#region Properties
public string Foo { get; set; }
public Category Category
{
get { return this._category; }
set { this._category = value; }
}
#endregion
#region IXmlSerializable
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
Enum.TryParse(reader.Name, out _category);
reader.Read();
Foo = reader.ReadElementContentAsString("Foo", "");
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
writer.WriteStartElement(this.Category.ToString(), "");
writer.WriteElementString("Foo", Foo);
writer.WriteEndElement();
}
#endregion
}
public enum Category
{
MyTypeA,
MyTypeB,
nil
}
}
Given the following class design:
public class AllUserCollections
{
public List<UserCollection> UserCollections { get; set; }
public AllUserCollections()
{
this.UserCollections = new List<UserCollection> ();
}
}
public class UserCollection
{
public string UserGroup { get; set; }
public Dictionary<int,User> Users { get; set; }
public UserCollection(string userGroup)
{
this.UserGroup = userGroup;
this.Users = new Dictionary<int, User> ();
}
}
public class User
{
public int ID { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public AgeGroup UserAgeGroup { get; set; }
}
public enum AgeGroup
{
Twenties,
Thirties,
Fourties,
}
How can I serialize this to XML using my existing serialization class?
public static class HardDriveService
{
private static string docsFolderPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
private const string fileName = "AllUserCollections.xml";
private static string filePath = Path.Combine(docsFolderPath, fileName);
private static bool FileExists(string fullFilePath)
{
if (File.Exists (fullFilePath))
return true;
return false;
}
public static void Save(AllUserCollections allUserCollections)
{
if (FileExists(filePath))
{
File.Delete (filePath);
}
XmlSerializer serializer = new XmlSerializer(allUserCollections.GetType());
using(StreamWriter writer = new StreamWriter(filePath))
{
serializer.Serialize(writer.BaseStream, allUserCollections);
}
}
public static AllUserCollections Read()
{
AllUserCollections allUserCollections = new AllUserCollections();
XmlSerializer serializer = new XmlSerializer(allUserCollections.GetType());
if (FileExists(filePath))
{
StreamReader reader = new StreamReader(filePath);
object deserialized = serializer.Deserialize(reader.BaseStream);
allUserCollections = (AllUserCollections)deserialized;
}
return allUserCollections;
}
}//End of class.
ISSUES
My code seems to fail on this line -
XmlSerializer serializer = new XmlSerializer(allUserCollections.GetType());
I wonder if it's to do with the class needing to be explicitly marked as "serializable"? How would I do this?
Usage
This code will run on an iphone and save/read directly from an app to XML on the iPhone hard drive.
XMLSerializer doesn't support Dictionary out of the box. Your UserCollection class has a Dictionary. See this link for a workaround.
Why doesn't XmlSerializer support Dictionary?
Other than that the XMLSerializer requires that your classes have default constructors (UserCollection and User don't) and each of them must have the [Serializable] attribute.
You could use XElement to build up an XML format. You could use them along the following lines:
public static XElement ToXml(this User user)
{
if (user == null)
{
throw new ArgumentException("User can not be null.");
}
XElement userElement = new XElement("User");
userElement.Add(new XElement("ID", user.ID));
userElement.Add(new XElement("Name", user.Name));
userElement.Add(new XElement("Location", user.Location));
userElement.Add(new XElement("UserAgeGroup", user.UserAgeGroup));
return userElement;
}
public static string ToXml(this UserCollection userCollection)
{
if (userCollection == null)
{
throw new ArgumentException("UserCollection can not be null.");
}
XElement userCollectionElement = new XElement("UserCollection");
userCollectionElement.Add(new XElement("UserGroup", userCollection.UserGroup));
userCollectionElement.Add(new XElement("Users",
userCollection.Users.Select(x => new XElement("User", x.ToXml()));
return userCollectionElement;
}
Calling .ToString() on an XElement should give you an xml-formatted string.
FULL WORKING SOLUTION
Data Model
using System;
using System.Collections.Generic;
namespace iPhoneHardDriveCRUDPrototype
{
[Serializable]
public class AllUserCollections
{
public List<UserCollection> UserCollections { get; set; }
public AllUserCollections()
{
this.UserCollections = new List<UserCollection> ();
}
}
[Serializable]
public class UserCollection
{
public string UserGroup { get; set; }
public SerializableDictionary<int,User> Users { get; set; }
public UserCollection()
{
this.Users = new SerializableDictionary<int, User> ();
}
public UserCollection(string userGroup)
{
this.UserGroup = userGroup;
this.Users = new SerializableDictionary<int, User> ();
}
}
[Serializable]
public class User
{
public int ID { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public AgeGroup UserAgeGroup { get; set; }
public User()
{
}
}
[Serializable]
public enum AgeGroup
{
Twenties,
Thirties,
Fourties,
}
}
Serializable Dictionary
using System;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace iPhoneHardDriveCRUDPrototype
{
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
bool wasEmpty = reader.IsEmptyElement;
reader.Read();
if (wasEmpty)
return;
while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
reader.ReadStartElement("item");
reader.ReadStartElement("key");
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("value");
TValue value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
this.Add(key, value);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
foreach (TKey key in this.Keys)
{
writer.WriteStartElement("item");
writer.WriteStartElement("key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
writer.WriteStartElement("value");
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
}//End of Class....
}
Serializer
using System;
using System.IO;
using System.Xml.Serialization;
using System.Reflection;
using System.Collections.Generic;
namespace iPhoneHardDriveCRUDPrototype
{
public static class HardDriveService
{
private static string docsFolderPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
private const string fileName = "AllUserCollections.xml";
private static string filePath = Path.Combine(docsFolderPath, fileName);
private static bool FileExists(string fullFilePath)
{
if (File.Exists (fullFilePath))
return true;
return false;
}
public static void Save(AllUserCollections allUserCollections)
{
if (FileExists(filePath))
{
File.Delete (filePath);
}
XmlSerializer serializer = new XmlSerializer(allUserCollections.GetType());
using(StreamWriter writer = new StreamWriter(filePath))
{
serializer.Serialize(writer.BaseStream, allUserCollections);
}
}
public static AllUserCollections Read()
{
AllUserCollections allUserCollections = new AllUserCollections();
XmlSerializer serializer = new XmlSerializer(allUserCollections.GetType());
if (FileExists(filePath))
{
StreamReader reader = new StreamReader(filePath);
object deserialized = serializer.Deserialize(reader.BaseStream);
allUserCollections = (AllUserCollections)deserialized;
}
return allUserCollections;
}
}//End of class.
}
Here you have 2 choices XmlSerializer(which will not work with Dictionary or List type deserialization ) or you can use DataContractSerializer which added in .net 3.0 and has a lot advantages here are few: form this post
optimized for speed (about 10% faster than XmlSerializer, typically)
in "opt-in" - only stuff you specifically mark as [DataMember] will be serialized
doesn't support XML attributes (for speed reasons)
Note : you should add reference to the C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0\System.Runtime.Serialization.dll
//to serialize
SerializeHelper.Serialize("your filename" ,new AllUserCollections());
// deserialize
var usertCollections = SerializeHelper.Deserialize<AllUserCollections>("yourfile name");
//code
[DataContract]
public class AllUserCollections
{
public List<UserCollection> UserCollections { get; set; }
public AllUserCollections()
{
this.UserCollections = new List<UserCollection>();
}
}
[DataContract()]
public class UserCollection
{
[DataMember]
public string UserGroup { get; set; }
[DataMember]
public Dictionary<int, User> Users { get; set; }
public UserCollection(string userGroup)
{
this.UserGroup = userGroup;
this.Users = new Dictionary<int, User>();
}
}
[DataContract()]
public class User
{ [DataMember]
public int ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Location { get; set; }
[DataMember]
public AgeGroup UserAgeGroup { get; set; }
}
[DataContract]
public enum AgeGroup
{
Twenties,
Thirties,
Fourties,
}
public static class SerializeHelper
{
public static void Serialize<T>(string fileName, T obj)
{
using (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)
{
T des;
using (FileStream fs = new FileStream(fileName,FileMode.Open))
{
XmlDictionaryReader reader =
XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
DataContractSerializer ser = new DataContractSerializer(typeof(T));
des =
(T)ser.ReadObject(reader, true);
reader.Close();
fs.Close();
}
return des;
}
}