In C#, How can I serialize Queue<>? (.Net 2.0) - c#

At the XmlSerializer constructor line the below causes an InvalidOperationException which also complains about not having a default accesor implemented for the generic type.
Queue<MyData> myDataQueue = new Queue<MyData>();
// Populate the queue here
XmlSerializer mySerializer =
new XmlSerializer(myDataQueue.GetType());
StreamWriter myWriter = new StreamWriter("myData.xml");
mySerializer.Serialize(myWriter, myDataQueue);
myWriter.Close();

It would be easier (and more appropriate IMO) to serialize the data from the queue - perhaps in a flat array or List<T>. Since Queue<T> implements IEnumerable<T>, you should be able to use:
List<T> list = new List<T>(queue);

Not all parts of the framework are designed for XML serialization. You'll find that dictionaries also are lacking in the serialization department.
A queue is pretty trivial to implement. You can easily create your own that also implements IList so that it will be serializable.

if you want to use the built in serialization you need to play by its rules, which means default ctor, and public get/set properties for the members you want to serialize (and presumably deserialize )
on the data type you want to serialize (MyData)

In my case i had a dynamic queue and i had to save and load the state of this one.
Using Newtonsoft.Json:
List<dynamic> sampleListOfRecords = new List<dynamic>();
Queue<dynamic> recordQueue = new Queue<dynamic>();
//I add data to queue from a sample list
foreach(dynamic r in sampleListOfRecords)
{
recordQueue.Enqueue(r);
}
//Serialize
File.WriteAllText("queue.json",
JsonConvert.SerializeObject(recordQueue.ToList(), Formatting.Indented));
//Deserialize
List<dynamic> data =
JsonConvert.DeserializeObject<List<dynamic>>(File.ReadAllText("queue.json"));

Related

Using reflection to convert a non-generic dictionary to a generic one, without the generic parameters

I'm working on custom XML serialization for this PropertyList DTD, and so far I've fully covered all the types except "dict". Some of the dicts are essentially objects like this:
<key>1</key>
<dict>
<key>Track ID</key><integer>1</integer>
<key>Name</key><string>Baby</string>
<key>Artist</key><string>Justin Bieber</string>
[...]
</dict>
Which I've already handled.
property.SetValue(obj, xmlReader.ReadElementContentAs(propertyType, null));
For arrays, I was able to use the untyped Array class (using the ArrayList class to build it), which lets one work with type variables instead of generics, and then conveniently can go straight into the SetValue method and automatically converted to the int[] or whatever other generic is in the object.
ArrayList array = new ArrayList();
do
{
array.Add(GetDictValue(arrayReader, elementType));
}
while (arrayReader.ReadToFollowing(elementTypeName));
property.SetValue(obj, array.ToArray(elementType));
But I cannot find any such way to do this for dictionaries. Hashtable cannot convert to a generic Dictionary<TKey, TValue> without the generic parameters.
I would create a 2nd xmlreader to read the child :
XmlReader reader = XmlReader.Create(#"c:\temp\test.xml");
reader.ReadToFollowing("ENVELOPE");
StringReader sReader = new StringReader(reader.ReadInnerXml());
XmlReader childReader = XmlReader.Create(sReader);
childReader.MoveToContent();
reader.MoveToContent();

DataContractJsonSerializer dynamic object deserialization

I would like to go with DataContractJsonSerializer instead of any third party libs like Json.NET I need to deserialize Json stream which can be one of my C# classes, and I dont know which one it is what i want to do is Deserialize json data -> determine type of this object -> do something with deserialized object according to type of this object. Is there anything to do with DataContractJsonSerializer.KnownTypes Property? Im really new to json.
what i want to do is Deserialize json data -> determine type of this object -> do something with deserialized object according to type of this object. Is there anything to do with DataContractJsonSerializer.KnownTypes Property?
Yes, it is related to the known types. Firstly, you need to specify the type you want to de-serialize in the constructor function. Then you can specify the types may be present in may be present in the object graph.
DataContractJsonSerializer Constructor (Type, IEnumerable)
But I still recommend you using the JSON.NET which will be easier than DataContractJsonSerializer, and the performance is even better. In ASP.NET Web API, JSON.NET is the default JSON serializer.
or JavaScriptSerializer
var jss = new JavaScriptSerializer();
var dict = jss.Deserialize<Dictionary<string, dynamic>>(strRet);
StringBuilder sbErr = new StringBuilder(string.Format("{0} ({1}): {2}", rep.StatusDescription, dict["code"], Environment.NewLine));
if ((dict["errors"] is Dictionary<string, dynamic>)) {
foreach (KeyValuePair<string, dynamic> item in dict["errors"]) {
sbErr.AppendFormat("{0}=", item.Key);
foreach (string item2 in item.Value)
sbErr.AppendFormat("{0}. ", item2);
}
}

Read HttpRuntime.Cache item as read-only

I am using a HttpRuntime.Cache to store a list of objects that will be accessing frequently across sessions.
I use the following line of code to get the item from the cache:
List<chartData_Type> _chartData =
(List<chartData_Type>)HttpRuntime.Cache.Get("rollingMonth");
But, unfortunately when I update the _chartData, it updates the cached item too.
How can I simply get a copy of the cached item?
That is the way which .NET works because Cache just reference to the pointer of List. Don't know whether you chartData_Type is value type or reference type.
If value type, it is easy to use:
List<chartData_Type> list = new List<chartData_Type>(_chartData);
But if reference type, it comes to complicated, you need to implement DeepCopy method for your class, then do DeepCopy for each object in list.
DeepClone method:
public static class CloneHelper
{
public static T DeepClone<T>(T obj)
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
return (T) formatter.Deserialize(ms);
}
}
}
In order to use this method, class chartData_Type must be marked [Serializable]:
[Serializable]
class chartData_Type
{}
So, you can do deep clone manually:
var cloneChartData = _chartData.Select(d =>
CloneHelper.DeepClone<chartData_Type>(d))
.ToList();
Use:
List<chartData_Type> list = new List<chartData_Type>(_chartData);
It will copy all items from _chartData to list.
List is a reference type and _chartData holds the address of the original object stored in the cache. That is why when you update _chartData, it updates the cached object too. If you want a separate object then clone the cached object. See below reference
http://www.codeproject.com/Articles/33364/ASP-NET-Runtime-Cache-Clone-Objects-to-Preserve-Ca
http://www.codeproject.com/Articles/45168/ASP-NET-Runtime-Cache-Clone-Objects-to-Preserve-Ca

How to deep copy a matrix in C#?

I got a List<List<CustomClass>>, where CustomClass is a reference type.
I need to make a full deep copy of this matrix into a new one. Since I want a deep copy, each CustomClass object in the matrix has to be copied into the new matrix.
How would you do that in an efficient way?
For a CustomClass that implements ICloneable, this isn't very difficult:
var myList = new List<List<CustomClass>>();
//populate myList
var clonedList = new List<List<CustomClass>>();
//here's the beef
foreach(var sublist in myList)
{
var newSubList = new List<CustomClass>();
clonedList.Add(newSubList);
foreach(var item in sublist)
newSublist.Add((CustomClass)(item.Clone()));
}
You can make this work in a similar way with any "DeepCopy"-type method, if you feel you don't want to implement ICloneable (I would recommend using the built-in interface though).
One easier way to serialize the whole object and then deserialize it again, try this extension method:
public static T DeepClone<T>(this T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
USAGE
List<List<CustomClass>> foobar = GetListOfListOfCustomClass();
List<List<CustomClass>> deepClonedObject = foobar.DeepClone();
There are two possibilities:
Implement the ICloneable interface on your CustomClass, then you can clone your objects.
If the class can be serialized, serialize it to a memory stream and deserialize it from there. That will create a copy of it.
I would prefer to take the first alternative, because I think serializing / deserializing is slower than cloning via ICloneable.
Assuming you have a Copy method which can duplicate CustomClass objects:
var newMatrix = oldMatrix
.Select(subList => subList.Select(custom => Copy(custom)).ToList())
.ToList();

Generic JSON parser in .NET / WPF?

I've read lots of tutorials on how to deserialize a JSON object to an object of a particular using DataContractJsonSerializer. However, I'd like to deserialize my object to a Dictionary consisting of either Strings, Arrays or Dictionaries, such as System.Json does with SilverLight when I say JsonObject.Parse(myJSONstring).
Is there an equivalent to System.Json that I can use in my WPF project?
(just a short background: I'm fetching JSON objects that have way to much info, and I just want to use a little bit to fill out a String array)
Cheers
Nik
Just use .NET's built-in JavaScriptSerializer.
var jss = new JavaScriptSerializer();
var data = jss.Deserialize<dynamic>(jsonString);
//"data" actually implements IDictionary<string, object>
var p1 = data["Property1"];
var p2 = data["Property2"];
Don't forget to reference "System.Web.Extensions"
Take a look at the C# section (scoll to the bottom) of http://json.org/, they have several implementations of serializers and parsers that should help.
I successfully use JayRock: http://jayrock.berlios.de/
public class JayRockMarshaller : IMarshaller
{
public ICollection Read(string text)
{
return (ICollection)new ImportContext().Import(new JsonTextReader(new StringReader(text)));
}
public string Write(ICollection objectToMarshal)
{
var writer = new StringWriter();
new ExportContext().Export(objectToMarshal, new JsonTextWriter(writer));
return writer.ToString();
}
}
Works for both Dictionaries and Lists like a dream.
Also look at https://github.com/jlarsson/Kiwi.Json it handles all sorts of datatypes and you can easily create your own converter if the built in doesn't fit.
There's blog where you can find samples on this for example: http://dancewithcode.wordpress.com/2012/03/24/case-study-custom-json-converter-for-datatable/

Categories

Resources