Serialization: How to Deserialize in C# - c#

How can I deserialize the string based on what I have done in this method? Basically, what I have here is to pass the string through the network using serialization and deserialize the string in order to convey the message. But once I managed to receive the message, I have no idea if what I'm doing is correct. Here's the code:
string ConvertToString(FrogGame np, Frog1 pm, Frog2 pm2) //Serialization. the three parameters are the classes.
{
XmlSerializer sendSerializer = new XmlSerializer(typeof(FrogGame),new Type[]{typeof(Frog1),typeof(Frog2)});
StreamWriter myWriter = new StreamWriter(#"pad1.xml");
sendSerializer.Serialize(myWriter, np);
sendSerializer.Serialize(myWriter, pm);
sendSerializer.Serialize(myWriter, pm2);
return myWriter.ToString();
} //Overall, I serialize it into string
Once I pass the string through the network, I want to deserialize it in order the pass the message to the classes. How do I continue here onwards? How can I edit? The code:
void StringReceived(string str) //so str is myWriter.ToString()
{
XmlSerializer revSerializer = new XmlSerializer(typeof(FrogGame), new Type[] { typeof(Frog1), typeof(Frog2) });
FileStream myFileStream = new FileStream(#"pad1.xml", FileMode.Open);
FrogGame b = (FrogGame)revSerializer.Deserialize(myFileStream);
if (b is Frog1)
{
if (Network.IsServer())
{
pm = (Frog1)b;
pm.Position.Y = b.pm.Position.Y;
pm.Position.X = b.pm.Position.X;
}
else
{
System.Diagnostics.Debug.WriteLine("BAD Message: " + msg);
}
}
else if (b is Frog2)
{
if (Network.IsClient())
{
pm2 = (PaddleMessage2)b;
pm2.Position.Y = b.pm2.Position.Y;
pm2.Position.X = b.pm2.Position.X;
}
else
{
System.Diagnostics.Debug.WriteLine("BAD Message: " + msg);
}
}
}

I might misinterpret your problem, but I why don't you put all the thing you want to save in a class and do it like this (plus, if you use class, your data "transportation" and "management" will be much easier) :
SERIALIZATION
XmlSerializer serializer = new XmlSerializer(typeof(FrogGameData));
TextWriter textWriter = new StreamWriter("FrogGameSaveFile.xml");
serializer.Serialize(textWriter, _frogGameData);
textWriter.Close();
DESERIALIZATION
XmlSerializer deserializer = new XmlSerializer(typeof(FrogGameData));
TextReader textReader = new StreamReader("FrogGameSaveFile.xml");
_frogGameData = (FrogGameData)deserializer.Deserialize(textReader);
textReader.Close();
Note : The need-to-be-saved field should have property, because the tag in the XML will mimic the property name.
Additional Note : FrogGameData is not different than a normal class for automatic serialization like this. The XML will mimic your property order in the class for the one in the XML file.
But if you wanna need to rearrange the XML tag placement, you could do something like [XmlElement(Order = 1)],[XmlElement(Order = 2)], etc on top of your property to customize the order in XML file.
UPDATE
In case you need it, this is an example of your FrogGameData class :
public class FrogGameData
{
private Frog _frog1;
private Frog _frog2;
public Frog Frog1
{
get { return _frog1; }
set { _frog1 = value; }
}
public Frog Frog2
{
get { return _frog2; }
set { _frog2 = value; }
}
}
And the XML will pretty much like this :
<?xml version="1.0" encoding="utf-8"?>
<FrogGameData>
<Frog1>Something-depends-on-your-data</Frog1>
<Frog2>Something-depends-on-your-data</Frog2>
</FrogGameData>
But, if your class is (Note the XmlElement part) :
public class FrogGameData
{
private Frog _frog1;
private Frog _frog2;
[XmlElement(Order = 2)]
public Frog Frog1
{
get { return _frog1; }
set { _frog1 = value; }
}
[XmlElement(Order = 1)]
public Frog Frog2
{
get { return _frog2; }
set { _frog2 = value; }
}
}
Then, your XML will be :
<?xml version="1.0" encoding="utf-8"?>
<FrogGameData>
<Frog2>Something-depends-on-your-data</Frog2>
<Frog1>Something-depends-on-your-data</Frog1>
</FrogGameData>

Related

Setting an XML attribute in the model

I need to set an attribute in my XML. I require the following:
<finAccount version="1.00">
Here is my model so far
[XmlAttribute("version")]
[XmlType("finPOWERConnect")]
public class ApplicationData
{
public List<Account> Accounts;
}
[XmlType("finAccount")]
public class Account
{
//Account stuff
}
The following function serialises my object to xml using the above model.
public Boolean SerialiseObjectToXmlString(Object obj, ref string xml)
{
System.IO.MemoryStream ms = null;
bool Ok = true;
XmlSerializer xmlSerializer = null;
xml = "";
//Serialise
try
{
xmlSerializer = new XmlSerializer(obj.GetType());
ms = new MemoryStream();
xmlSerializer.Serialize(ms, obj);
xml = System.Text.Encoding.UTF8.GetString(ms.GetBuffer(), 0, (int)ms.Length);
ms.Close();
}
catch(Exception ex)
{
Ok = false;
xml = ex.Message;
}
finally
{
if (ms != null) ms.Dispose();
}
return Ok;
}
I have looked at several examples that set the attribute in the above method however I use this method all throughout the application. Is there a way to set the xml attribute (version="1.00) in the model?
Try this. Class should be XmlRoot and arrays should be XmlElement. The XmlElement avoids adding two layer of the same tag to code. Try without XmlElement and you will see the difference.
[XmlRoot("finPOWERConnect")]
public class ApplicationData
{
[XmlElement("finAccount")]
public List<Account> Accounts {get; set; }
}
[XmlRoot("finAccount")]
public class Account
{
[XmlAttribute("version")]
public string Version { get; set; }
//Account stuff
}
​

Serialize a class that contains a list?

I may be doing this all wrong here, but I created a class that contains a list and I need to serialize that list. (Is there a better way or other suggestions to have multiple interfaces without a list?)
I've been doing okay with serializing custom classes, but this one for some reason isn't working out.
[XmlRoot("interfaces", Namespace = "")]
[XmlInclude(typeof(Interface))]
public class Interfaces
{
[XmlArray("interfaces")]
[XmlArrayItem("interface")]
List<Interface> _IflList = new List<Interface>();
public List<Interface> IflList
{
get { return _IflList; }
set { _IflList = value; }
}
public void Add(Interface objInterface)
{
_IflList.Add(objInterface);
}
}
[XmlType("interface")]
public class Interface
{
string _name;
public string name
{
get { return _name; }
set { _name = value; }
}
public Interface(string name)
{
this._name = name;
}
}
I get the error There was an error reflecting type 'JunOSConfig.Interfaces' when trying to serialize with:
public string SerializeObject(object objToSerialize, bool StripXmlVer, bool FormatOutput)
{
string strReturn = "";
XmlSerializerNamespaces xns = new XmlSerializerNamespaces();
xns.Add("", "");
Type objType = typeof(JunOSConfig.Interfaces);
XmlSerializer xs = new XmlSerializer(objToSerialize.GetType());
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = StripXmlVer;
StringWriter sw = new StringWriter();
XmlWriter xw = XmlWriter.Create(sw, xws);
xs.Serialize(xw, objToSerialize, xns);
strReturn = sw.ToString();
if (FormatOutput)
{
return Convert.ToString(XElement.Parse(strReturn));
}
else
{
return strReturn;
}
}
In addition to your constructor with one parameter
public Interface(string name)
{
this._name = name;
}
you will need another, parameterless constructor, like
public Interface()
{
}
If you do not declare a constructor yourself, a constructor without
parameters will be generated.
Then it should work.

Custom XML serialization with inheritance

I have the following class structure which I want to serialize:
[XmlRoot("SomeClass")]
public class SomeClass
{
private BaseClass[] _itemArray;
public BaseClass[] ItemArray
{
get { return _itemArray; }
set { _itemArray = value; }
}
public PPSPStatReportMessage()
: base()
{
}
}
public class SomeOtherClass
{
private int _property5;
[XmlAttribute("Property5")]
public int Property5
{
get { return _property5; }
set { _property5 = value; }
}
private string _property6;
[XmlText()]
public string Property6
{
get { return _property6; }
set { _property6 = value; }
}
public SomeOtherClass()
{
}
}
[XmlInclude(typeof(DerivedClass1))]
[XmlInclude(typeof(DerivedClass2))]
[XmlRoot("BaseClass")]
[XmlType("")]
public class BaseClass
{
private string _property1;
[XmlAttribute("Property1")]
public string Property1
{
get { return _property1; }
set { _property1 = value; }
}
public SomeClass(string PropertyVal)
{
_property1 = PropertyVal;
}
}
[XmlRoot("BaseClass")]
[XmlTypeAttribute(Namespace = "")]
public class DerivedClass1 : BaseClass
{
private string _property2;
[XmlAttribute("Property2")]
public string Property2
{
get { return _property2; }
set { _property2 = value; }
}
private SomeOtherClass _property3;
[XmlElement("SomeOtherClass")]
public SomeOtherClass Property3
{
get { return _property3; }
set { _property3 = value; }
}
public DerivedClass()
: base("PropertyVal1")
{
}
}
[XmlRoot("BaseClass", Namespace = "")]
[XmlType("")]
public class DerivedClass2 : BaseClass
{
private Int64 _property4;
[XmlAttribute("Property4")]
public Int64 Property4
{
get { return _property4; }
set { _property4 = value; }
}
public DerivedClass2()
: base("PropertyVal2")
{
}
}
And this is the method I use to serialize SomeClass:
public static string SerializeXML(object Value, System.Type ObjectType)
{
XmlSerializer serializer = new XmlSerializer(ObjectType);
XmlSerializerNamespaces namespaceSerializer = new XmlSerializerNamespaces();
namespaceSerializer.Add("", "");
StringWriter ms = new StringWriter();
serializer.Serialize(ms, Value, namespaceSerializer);
return ms.ToString();
}
This method generates an XML structure that looks like the following:
<?xml version="1.0" encoding="utf-16"?>
<SomeClass>
<ItemArray>
<BaseClass d3p1:type="DerivedClass1" Property1="PropertyVal1" Property2="123" xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance">
<SomeOtherClass Property5="0" >STRING DATA</SomeOtherClass>
</BaseClass>
<BaseClass d3p1:type="DerivedClass2" Property="PropertyVal2" Property4="456" xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance" />
</ItemArray>
</SomeClass>
However, I need to omit the d3p1:type and xmlns:d3p1 attributes and generate an XML structure that looks like this:
<?xml version="1.0" encoding="utf-16"?>
<SomeClass>
<ItemArray>
<BaseClass Property1="PropertyVal1" Property2="123">
<SomeOtherClass Property5="0" >STRING DATA</SomeOtherClass>
</BaseClass>
<BaseClass Property="PropertyVal2" Property4="456" />
</ItemArray>
</SomeClass>
As you can see in the code, I've tried to use XmlType and XmlTypeAttribute, but without success.
Any advice on how can I generate the XML structure as described above (without d3p1:type and xmlns:d3p1 attributes)?
Do you need the subclass elements to be called "BaseClass" - or would the name of the derived class do?
I am serializing similar subclass structures, and also wanted to get rid of the "d3p1:type" and "xmlns:d3p1" tags - instead replacing the "BaseClass" tags with derived class tags. So it is possible to generate xml for your example:
<ItemArray>
<DerivedClass1 Property1="PropertyVal1" Property2="123">
....
</DerivedClass1>
You're using an XmlInclude attribute on your BaseClass to let the serliazer know which derived classes to expect. Instead, you can tell the serializer about the expected subtypes on each element:
public class SomeClass
{
private BaseClass[] _itemArray;
[XmlElement(typeof(DerivedClass1))]
[XmlElement(typeof(DerivedClass2))]
public BaseClass[] ItemArray
{
get { return _itemArray; }
set { _itemArray = value; }
}
Eliminating the "type" attributes. Deserialiazation will also work fine.
You cannot accomplish what you want directly.
If the type being serialized isn't the exact type contained, .NET has to track what the type really is to allow proper deserialization.
To accomplish what you want - use RegEx.Replace() or other post-processing to replace the namespaces.
(e.g. serializing Object which is really a String will cause this problem).
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.Indent = true;
using (XmlWriter writer = XmlWriter.Create(file, settings))
{
XmlSerializer serializer = new XmlSerializer(source.GetType());
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
// ...
}

I get an exception during deserialization

I get this message when running the code below:
There is an error in XML document (6, 22).
namespace N1
{
public class InputEntry
{
//FieldName is a class tht is generated from an XSD which has complex type Name and value
private Field fields;
public Field[] Fields
{
get { return this.fields; }
set { this.fields= value; }
}
public string FieldName
{
get{return this.fieldName;}
set { this.fieldName = value; }
}
public string FieldValue
{
get {return this.fieldValue; }
set {this.fieldValue = value;}
}
}
public class B
{
public void Method1()
{
InputEntry inputEntry = new InputEntry();
//we some how get the values from user and assign them to
Field f1 = new Field();
f1.FieldName = "PRINTLINE00";
f1.FieldValue = "DENIAL STATE" ;
}
private void Method2(InputEntry inputEntry)
{
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(InputEntry));
System.IO.StringWriter inputStr = new System.IO.StringWriter(CultureInfo.InvariantCulture);
serializer.Serialize(inputStr, inputEntry);
string ipEntry = inputStr.ToString();
Method3(ipEntry);
}
private void Method3(string ipEntry)
{
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(InputEntry));
System.IO.StringReader inputStr = new System.IO.StringReader(ipEntry);
InputEntry inputEntry = (InputEntry)serializer.Deserialize(inputStr);
}
}
}
// when client configues input data as
// <FieldName>PRINTLINE00</FieldName> <FieldValue>DENIAL STATE</FieldValue>,
//I get an exception when the same data deserialised
//Exception is:-
String:
<?xml version="1.0" encoding="utf-16"?>
<InputEntry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Fields>
<Field>
<FieldName>PRINTLINE00</FieldName>
<FieldValue>DENIAL STATE 217</FieldValue>
</Field>
</Fields>
</InputEntry>
Aside from the fact that you're missing a closing Fields tag, you've also tried to serialise Unicode character U+001B... which unfortunately isn't supported in XML.
That's an "escape" character... did you really want it in the string to start with? It could be that you can just add validation (or trimming) in your code.
There's a missing </Fields> tag in your xml document.
You need to turn off character checking, something like this:
serializer.Deserialize (XmlReader.Create (inputStr, new XmlReaderSettings
{ CheckCharacters = false, }))
<FieldName>PRINTLINE00</FieldName> <FieldValue**>**DENIAL STATE</FieldValue>
missing an <

Storing entity in XML, using MVVM to read/write in WPF Application

Say I've a class (model) called Instance with Properties DatbaseHostname, AccessManagerHostname, DatabaseUsername and DatabasePassword
public class Instance
{
private string _DatabaseHostname;
public string DatabaseHostname
{
get { return _DatabaseHostname; }
set { _DatabaseHostname = value; }
}
private string _AccessManagerHostname;
public string AccessManagerHostname
{
get { return _AccessManagerHostname; }
set { _AccessManagerHostname = value; }
}
private string _DatabaseUsername;
public string DatabaseUsername
{
get { return _DatabaseUsername; }
set { _DatabaseUsername = value; }
}
private string _DatabasePassword;
public string DatabasePassword
{
get { return _DatabasePassword; }
set { _DatabasePassword = value; }
}
}
I'm looking for a sample code to read/write this Model to XML (preferably linq2XML) => storing 1:n instances in XML.
i can manage the the view and ViewModel part myself, although it would be nice if someone had a sample of that part too..
Well, you could use Linq to XML, but your class is a perfect candidate for XML Serialization, which is much simpler IMHO :
var list = new List<Instance>();
...
// Serialization
var xs = new XmlSerializer(typeof(List<Instance>));
using (var writer = XmlWriter.Create(filename))
{
xs.Serialize(writer, list);
}
...
// Deserialization
using (var reader = XmlReader.Create(filename))
{
list = xs.Deserialize(reader) as List<Instance>;
}
Not sure how you want your xml structured, but this should work:
List<Instance> instances = new List<Instance>();
// Get your instances here...
var baseNode = new XElement("Instances");
instances.ForEach(instance => baseNode.Add("Instance",
new XAttribute("DatabaseHostname", instance.DatabaseHostname),
new XAttribute("AccessManagerHostname", instance.AccessManagerHostname),
new XAttribute("DatabaseUsername", instance.DatabaseUsername),
new XAttribute("DatabasePassword", instance.DatabasePassword)));

Categories

Resources