I have a xml file which I am trying to deserialize.
I am implementing IXmlSerializable interface for Serialization and Deserialization.
I don't see any problem with the Serialization.
But with the deserialization I have few problems.
1). I am using xml reader's 'ReadToFollowing' for reading elements. With this approach I have to read the values in the order of elements. If there is any mismatch in the order I am not able to read the remainig values.
2). As per my requirement I have to provide backward compatibility in deserializing the xml. Because of this when I load some of the old version xml files(which may not contain all the elements as the latest version xml), 'ReadToFollowing' throwing exceptions.
Latest version Xml
<LEFTSECTION>
<DATA />
<FONTNAME>Arial</FONTNAME>
<FONTSTYLE>Regular</FONTSTYLE>
<FONTSIZE>10</FONTSIZE>
<TEXTCOLOR>-16777216</TEXTCOLOR>
<STRIKEOUT>0</STRIKEOUT>
<UNDERLINE>0</UNDERLINE>
<BORDER>0</BORDER>
<IMAGE>0</IMAGE>
<IMAGENAME />
<ALIGNMENT>4</ALIGNMENT>
<SECTIONHEIGHT>0.5454546</SECTIONHEIGHT>
<SECTIONWIDTH>0.33</SECTIONWIDTH>
</LEFTSECTION>
Old version Xml
<LEFTSECTION>
<DATA>asas#APP_OEM_NAME#</DATA>
<FONTNAME>Arial Unicode MS</FONTNAME>
<FONTSTYLE>Regular</FONTSTYLE>
<FONTSIZE>10</FONTSIZE>
<TEXTCOLOR>-16777216</TEXTCOLOR>
<STRIKEOUT>0</STRIKEOUT>
<UNDERLINE>0</UNDERLINE>
<BORDER>0</BORDER>
<IMAGE>0</IMAGE>
<IMAGENAME>
</IMAGENAME>
</LEFTSECTION>
Please help me on this.
Okay. I've had a play and this is what I've come up with:
Serializeable class:
[Serializable]
[XmlRoot("LEFTSECTION")]
public class NewClass
{
[XmlElement("DATA")]
[System.ComponentModel.DefaultValueAttribute("")]
public string Data;
[XmlElement("FONTNAME")]
public string FontName;
[XmlElement("FONTSTYLE")]
public string FontStyle;
[XmlElement("FONTSIZE")]
public int FontSize;
[XmlElement("TEXTCOLOR")]
public int TextColor;
[XmlElement("STRIKEOUT")]
public int Strikeout;
[XmlElement("UNDERLINE")]
public int Underline;
[XmlElement("BORDER")]
public int Border;
[XmlElement("IMAGE")]
public int Image;
[XmlElement("IMAGENAME")]
public string ImageName;
[System.ComponentModel.DefaultValue(0)]
[XmlElement("ALIGNMENT")]
public int Alignment;
[XmlElement("SECTIONHEIGHT")]
public double SectionHeight;
[XmlElement("SECTIONWIDTH")]
public double SectionWidth;
}
Then code in my test program:
NewClass test = new NewClass();
XmlSerializer serializer = new XmlSerializer(typeof(NewClass));
FileStream file = new FileStream("input.xml", FileMode.Open);
test = (NewClass) serializer.Deserialize(file);
file.Close();
file = new FileStream("old.xml", FileMode.Open);
test = (NewClass)serializer.Deserialize(file);
file.Close();
Contents of input.xml:
<?xml version="1.0" encoding="utf-8" ?>
<LEFTSECTION>
<DATA />
<FONTNAME>Arial</FONTNAME>
<FONTSTYLE>Regular</FONTSTYLE>
<FONTSIZE>10</FONTSIZE>
<TEXTCOLOR>-16777216</TEXTCOLOR>
<STRIKEOUT>0</STRIKEOUT>
<UNDERLINE>0</UNDERLINE>
<BORDER>0</BORDER>
<IMAGE>0</IMAGE>
<IMAGENAME />
<ALIGNMENT>4</ALIGNMENT>
<SECTIONHEIGHT>0.5454546</SECTIONHEIGHT>
<SECTIONWIDTH>0.33</SECTIONWIDTH>
</LEFTSECTION>
Contents of old.xml:
<LEFTSECTION>
<DATA>asas#APP_OEM_NAME#</DATA>
<FONTNAME>Arial Unicode MS</FONTNAME>
<FONTSTYLE>Regular</FONTSTYLE>
<FONTSIZE>10</FONTSIZE>
<TEXTCOLOR>-16777216</TEXTCOLOR>
<STRIKEOUT>0</STRIKEOUT>
<UNDERLINE>0</UNDERLINE>
<BORDER>0</BORDER>
<IMAGE>0</IMAGE>
<IMAGENAME>
</IMAGENAME>
</LEFTSECTION>
This populates my class correctly. Notice that on Data and Alignment properties of my class I set default values if they don't exist. Also they're all renamed from what is in the file.
I hope that this helps.
edit
Ah I see, you're stuck with IXmlSerializable methods for your classes.
Try this it's not pretty but it appears to work:
Here's my IXMLSerializable class:
public class XmlSerializableNewClass : IXmlSerializable
{
public string Data;
public string FontName;
public string FontStyle;
public int FontSize;
public int TextColor;
public int Strikeout;
public int Underline;
public int Border;
public int Image;
public string ImageName;
public int Alignment;
public double SectionHeight;
public double SectionWidth;
public string[]elementNames={"DATA", "FONTNAME", "FONTSTYLE","FONTSIZE","TEXTCOLOR","STRIKEOUT", "UNDERLINE", "BORDER", "IMAGE", "IMAGENAME", "ALIGNMENT", "SECTIONHEIGHT", "SECTIONWIDTH"};
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
//set default values
Data=string.Empty;
FontName = string.Empty;
FontStyle = string.Empty;
FontSize = 0;
TextColor = 0;
Strikeout = 0;
Underline = 0;
Border = 0;
Image = 0;
ImageName = string.Empty;
Alignment = 0;
SectionHeight = 0.0;
SectionWidth = 0.0;
reader.MoveToContent();
Boolean isEmptyElement= false;
isEmptyElement = reader.IsEmptyElement;
reader.ReadStartElement();
for (int i=0; i< elementNames.Length; i++)
{
isEmptyElement = reader.IsEmptyElement;
string s = reader.Name;
switch (s)
{
case "DATA":
if (!isEmptyElement)
{
Data = reader.ReadElementString("DATA");
}
else
{
Data = string.Empty;
reader.ReadStartElement();
}
break;
case "FONTNAME":
if (!isEmptyElement)
{
FontName = reader.ReadElementString("FONTNAME");
}
else
{
FontName = string.Empty;
reader.ReadStartElement();
}
break;
case "FONTSTYLE":
if (!isEmptyElement)
{
FontStyle = reader.ReadElementString("FONTSTYLE");
}
else
{
FontStyle = string.Empty;
reader.ReadStartElement();
}
break;
case "FONTSIZE":
if (!isEmptyElement)
{
FontSize = reader.ReadElementContentAsInt();
}
else
{
FontSize = 0;
reader.ReadEndElement();
}
break;
case "TEXTCOLOR":
if (!isEmptyElement)
{
TextColor = reader.ReadElementContentAsInt();
}
else
{
TextColor = 0;
reader.ReadStartElement();
}
break;
case "STRIKEOUT":
if (!isEmptyElement)
{
Strikeout = reader.ReadElementContentAsInt();
}
else
{
Strikeout = 0;
reader.ReadStartElement();
}
break;
case "UNDERLINE":
if (!isEmptyElement)
{
Underline = reader.ReadElementContentAsInt();
}
else
{
Underline = 0;
reader.ReadStartElement();
}
break;
case "BORDER":
if (!isEmptyElement)
{
Border = reader.ReadElementContentAsInt();
}
else
{
Border = 0;
reader.ReadStartElement();
}
break;
case "IMAGE":
if (!isEmptyElement)
{
Image = reader.ReadElementContentAsInt();
}
else
{
Image = 0;
reader.ReadStartElement();
}
break;
case "IMAGENAME":
if (!isEmptyElement)
{
ImageName = reader.ReadElementString("IMAGENAME");
}
else
{
ImageName = string.Empty;
reader.ReadStartElement();
}
break;
case "ALIGNMENT":
if (!isEmptyElement)
{
Alignment = reader.ReadElementContentAsInt();
}
else
{
Alignment = 0;
reader.ReadStartElement();
}
break;
case "SECTIONHEIGHT":
if (!isEmptyElement)
{
SectionHeight = reader.ReadElementContentAsDouble();
}
else
{
SectionHeight = 0;
reader.ReadStartElement();
}
break;
case "SECTIONWIDTH":
if (!isEmptyElement)
{
SectionWidth = reader.ReadElementContentAsDouble();
}
else
{
SectionWidth = 0;
reader.ReadEndElement();
}
break;
}
}
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
throw new NotImplementedException();
}
#endregion
}
I've gone a bit overboard with handling empty elements.
Here's the calling code, everything else is the same:
XmlSerializableNewClass test2 = new XmlSerializableNewClass();
System.Xml.XmlReaderSettings settings = new System.Xml.XmlReaderSettings();
settings.ConformanceLevel = System.Xml.ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
System.Xml.XmlReader reader = System.Xml.XmlReader.Create("input.xml", settings);
test2.ReadXml(reader);
reader = System.Xml.XmlReader.Create("old.xml", settings);
test2.ReadXml(reader);
Related
I am trying to convert the items in a list in to a string. but every time I convert it or display it all is shows is "TwitchIrcChar.user". If some one could help with this, it would be very helpful. sorry if noob question, but im new to lists. ive tried using convert.ToString and userlist.tostring. both gave the same output
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
namespace TwitchIrcChat
{
class User
{
static Random random = new Random();
public string UserName { get; set; }
public SolidColorBrush Color { get; set; }
public bool IsMod { get; set; }
public User(string username)
{
IsMod = false;
UserName = username;
randomColor();
}
public void setColor(SolidColorBrush color)
{
Color = color;
}
private void randomColor()
{
var temp = Brushes.White;
int randomColor = random.Next(0, 10);
switch (randomColor)
{
case 0:
temp = Brushes.Blue;
break;
case 1:
temp = Brushes.Green;
break;
case 2:
temp = Brushes.Red;
break;
case 3:
temp = Brushes.Purple;
break;
case 4:
temp = Brushes.Orange;
break;
case 5:
temp = Brushes.Yellow;
break;
case 6:
temp = Brushes.Gold;
break;
case 7:
temp = Brushes.Teal;
break;
case 8:
temp = Brushes.Cyan;
break;
case 9:
temp = Brushes.LightBlue;
break;
case 10:
temp = Brushes.Pink;
break;
}
Color = temp;
}
}
class UserList
{
public moderation q = new moderation();
public List<User> userList { get; set; }
public UserList()
{
userList = new List<User>();
}
public void Add(string userName)
{
bool isInList = false;
foreach (var item in userList)
{
if (item.UserName.Equals(userName))
{
isInList = true;
break;
}
}
if (!isInList)
{
var tempUser = new User(userName);
userList.Add(tempUser);
}
}
public void Remove(string userName)
{
int userLocation = -1;
for (int i = 0; i < userList.Count; i++)
{
if (userName.Equals(userList[i].UserName))
{
userLocation = i;
break;
}
}
try
{
userList.RemoveAt(userLocation);
}
catch (Exception)
{
}
}
public SolidColorBrush getColor(string username)
{
var temp = Brushes.White;
foreach (var item in userList)
{
if (item.UserName.Equals(username))
{
temp = item.Color;
}
}
return temp;
}
public void setColor(string username, string color)
{
if (userList.Count(s => s.UserName == username) == 0)
{
Add(username);
}
var user = userList.First(s => s.UserName == username);
var converter = new BrushConverter();
var brush = (SolidColorBrush)converter.ConvertFromString(color);
user.Color = brush;
}
public void Clear()
{
userList.Clear();
}
public void list()
{
Console.WriteLine("qweqweqweqwe");
for (int i = 0; i < userList.Count; i++) // Loop through List with for
{
Console.WriteLine(userList[i].ToString());
Console.WriteLine("qweqweqweqwe");
}
}
public void AddMod(string userName)
{
foreach (var item in userList)
{
//string a = item.ToString();
//q.writeToFile(a);
if (item.UserName.Equals(userName))
{
item.IsMod = true;
}
}
}
}
}
You could override ToString like others have suggested or if UserName is all you rally want you just do.
Console.WriteLine(userList[i].UserName.ToString());
or
Console.WriteLine(userList[i].UserName);
since its already a string
You have to override ToString() method in your class and return the desired string in that method. For instance if you want to return UserName when ToString() is called on an instance of User, you can do it like this:
public class User
{
public string UserName {get;set;}
public override string ToString()
{
return UserName;
}
}
If you don't do this, the default ToString() will return the name of the object's type.
This has nothing to do with lists, and everything to do with how you represent a custom object as a string.
The default behavior for .ToString() is exactly what you're seeing, outputting the name of the class. .NET has no way of intuitively knowing what you mean when you want to see an object as a string. You need to explicitly provide that logic by overriding .ToString() on your object.
For example, if you just want to see the user's name, it could be something as simple as:
public override string ToString()
{
return UserName;
}
Essentially, the question you need to ask yourself is, "Am I outputting a property on the User, or am I outputting the User itself?" If the latter, you'd definitely want to encapsulate that logic into a .ToString() override, since that logic may change over time. For example, if you ever want the string representation of a User to also show if the User is a "mod" (say, for example, with a * character), you would just add that in the override:
public override string ToString()
{
return string.Format("{0} {1}",
UserName,
IsMod ? "(*)" : string.Empty);
}
The default behavior of ToString() (inherited from System.Object) is to display the type name. If you want to change this behavior you must override ToString:
class User
{
...
public override string ToString()
{
return UserName + (IsMod ? " (moderator)" : "");
}
}
ToString is used automatically by Console.WriteLine, so you simply call it like this:
Console.WriteLine(userList[i]);
You can also add objects directly to listboxes for instance, as those use ToString as well in order to display the items.
listBox1.Items.Add(user);
I get an inconsistent accessibility error when trying to compile my C# code. I have googled it extensively, but all the cases and answers I find deal with some private-public inconstancy. I have not written private ANYWHERE in my code at all, I have checked and double checked. I read something somewhere that I could try "lowering the scope", but I have no idea what that means. Help.
Sorry for missing code, here it is on github:
https://gist.github.com/jyggorath/7589742
using System;
public class oblig5 {
// // // BEGIN GLOBAL 1 // // //
public const int STRLEN = 40;
public const int MAXPERSONER = 500;
public const int MAXLAG = 50;
public enum funksjon {trener, oppman, ingen};
// // // END GLOBAL 1 // // //
// // // BEGIN PERSON CLASS // // //
public class Person {
// // // privates:
public string navn;
public string adr;
public string mail;
public string klasse;
public int tlf;
public funksjon verv;
public int lagnr;
// // // publics:
// constructor
public Person() {
navn = ""; adr = ""; mail = ""; klasse = "";
tlf = 0; lagnr = 0;
verv = (funksjon)2;
}
// skriv:
public void skriv() {
Console.WriteLine("Navn: {0}\nAdresse: {1}\nMail: {2}\nKlasse: {3}\nTlf: {4}\nLagnr: {5}", navn, adr, mail, klasse, tlf, lagnr);
if (verv == (funksjon)0)
Console.WriteLine("Er Trener\n");
else if (verv == (funksjon)1)
Console.WriteLine("Er Oppmann\n");
else
Console.WriteLine("Har ikkeno verv\n");
lag[lagnr].skriv();
}
public void skriv2() {
Console.WriteLine("Navn: {0}\nAdresse: {1}\nMail: {2}\nKlasse: {3}\nTlf: {4}\n", navn, adr, mail, klasse, tlf);
}
// les:
public void les_data(int lnr) {
lagnr = lnr;
navn = les_str("Personens navn");
adr = les_str("Personens adresse");
mail = les_str("Personens mail");
klasse = les_str("Hvilke klasse går personen i?");
tlf = les_int("Personens telefonnr", 10000000, 99999999);
verv = les_enum();
}
// fil:
public void skriv_til_fil(System.IO.StreamWriter file) {
file.WriteLine(navn);
file.WriteLine(adr);
file.WriteLine(mail);
file.WriteLine(klasse);
file.WriteLine(tlf);
file.WriteLine((int)verv);
file.WriteLine(lagnr);
}
public void les_fra_fil(System.IO.StreamReader file, string nvn) {
navn = nvn;
adr = file.ReadLine();
mail = file.ReadLine();
klasse = file.ReadLine();
tlf = int.Parse(file.ReadLine());
verv = (funksjon)int.Parse(file.ReadLine());
lagnr = int.Parse(file.ReadLine());
}
// sammenligninger:
public bool har_navn(string t) {
return (navn == t);
}
public bool har_verv(funksjon v) {
return (verv == v);
}
public bool tilhorer_lag(int n) {
return (lagnr == n);
}
}
// // // END PERSON CLASS // // //
// // // BEGIN LAG CLASS // // //
public class Lag {
// // // privates:
public string navn;
public string adr;
public string mail;
public string hjemmeside;
// // // publics:
public Lag() {
navn = ""; adr = ""; mail = ""; hjemmeside = "";
}
public void skriv() {
Console.WriteLine("Lagnavn: {0}\nLagadresse: {1}\nLagmail: {2}\nLaghjemmeside: {3}\n", navn, adr, mail, hjemmeside);
}
public void les_data(string t) {
navn = t;
adr = les_str("Lagets adresse");
mail = les_str("Lagets mail");
hjemmeside = les_str("Lagets hjemmeside");
}
public bool har_navn(string t) {
return (navn == t);
}
}
// // // END LAG CLASS // // //
// // // BEGIN GLOBAL 2 // // //
// things:
public static Person[] personer = new Person[MAXPERSONER + 1];
public static Lag[] lag = new Lag[MAXLAG + 1];
public static int siste_person = 0, siste_lag = 0;
// funskjoner:
public static void skriv_meny() {
Console.WriteLine("\n\nFØLGENDE KOMMANDOER ER LOVLIG:");
Console.WriteLine("\tA = skriv ALT om En person");
Console.WriteLine("\tB = skriv ALLE trenere ELLER oppmenn");
Console.WriteLine("\tC = skriv ALT om et gitt lag");
Console.WriteLine("\tL = nytt Lag legges inn");
Console.WriteLine("\tP = ny Person legges inn");
Console.WriteLine("\tQ = Quit/Avslutt");
}
public static char les_char(string t) {
Console.Write(string.Concat("\n", t, ": "));
char retur = Console.ReadLine().ToUpper()[0];
return retur;
}
public static int les_int(string t, int min, int max) {
int retur = min - 1;
do {
Console.Write(string.Concat("\t", t, " (", min.ToString(), "-", max.ToString(), "): "));
retur = int.Parse(Console.ReadLine());
} while (retur < min || retur > max);
return retur;
}
public static string les_str(string t) {
return Console.ReadLine();
}
public static funksjon les_enum() {
char ch = '\0';
do {
Console.Write("\tT(rener) eller O(ppmann): ");
ch = Console.ReadLine().ToUpper()[0];
} while (ch != 'T' && ch != 'O');
return ((ch == 'T') ? (funksjon)0 : (funksjon)1);
}
public static int finn_person(string t) {
for (int i = 1; i <= siste_person; i++)
if (personer[i].har_navn(t))
return i;
return 0;
}
public static int finn_lag(string t) {
for (int i = 1; i <= siste_lag; i++)
if (lag[i].har_navn(t))
return i;
return 0;
}
public static void skriv_person() {
string nvn = les_str("Navn på person");
int person_nr = finn_person(nvn);
if (person_nr == 0)
Console.WriteLine("Personen fins ikke");
else
personer[person_nr].skriv();
}
public static void skriv_verv() {
funksjon v = les_enum();
for (int i = 1; i < siste_person; i++) {
if (personer[i].har_verv(v))
personer[i].skriv();
}
}
public static void skriv_lag() {
string lagnvn = les_str("Navn på lag");
int lagnr = finn_lag(lagnvn);
if (lagnr == 0)
Console.WriteLine("Laget fins ikke");
else {
lag[lagnr].skriv();
for (int i = 1; i <= siste_person; i++) {
if (personer[i].tilhorer_lag(lagnr))
personer[i].skriv2();
}
}
}
public static void nytt_lag() {
if (siste_lag < MAXLAG) {
string lagnvn = les_str("Lagets navn");
if (finn_lag(lagnvn) == 0) {
siste_lag++;
lag[siste_lag] = new Lag();
lag[siste_lag].les_data(lagnvn);
}
else
Console.WriteLine("Laget fins fra før!");
}
else
Console.WriteLine("Lag er full!");
}
public static void ny_person() {
if (siste_person < MAXPERSONER) {
string lagnvn = les_str("Hvilke lag tilhører personen?");
int lagnr = finn_lag(lagnvn);
if (lagnr != 0) {
siste_person++;
personer[siste_person] = new Person();
personer[siste_person].les_data(lagnr);
}
else
Console.WriteLine("Laget fins ikke!");
}
else
Console.WriteLine("Personer er fulle!");
}
public static void skriv_til_fil() {
System.IO.StreamWriter file = new System.IO.StreamWriter("personer.dta");
for (int i = 1; i <= siste_person; i++) {
personer[i].skriv_til_fil(file);
}
}
public static void les_fra_fil() {
string buffer;
try {
System.IO.StreamReader file = new System.IO.StreamReader("personer.dta");
while ((buffer = file.ReadLine()) != null) {
siste_person++;
personer[siste_person] = new Person();
personer[siste_person].les_fra_fil(file, buffer);
}
}
catch {
Console.WriteLine("Finner ikke filen!");
}
}
// // // END GLOBAL 2 // // //
// // // BEGIN MAIN // // //
public static void Main() {
char kommando;
les_fra_fil();
skriv_meny();
kommando = les_char("Ønske");
while (kommando != 'Q') {
switch (kommando) {
case 'A':
skriv_person(); break;
case 'B':
skriv_verv(); break;
case 'C':
skriv_lag(); break;
case 'L':
nytt_lag(); break;
case 'P':
ny_person(); break;
default:
skriv_meny();
break;
}
kommando = les_char("Ønske");
}
skriv_til_fil();
Console.WriteLine("\n");
}
// // // END MAIN // // //
}
Sorry for strange variable names. This is code ported from C++ assignments from my Norwegian teacher (I didn't change them 'cause I'm Norwegian as well, and I never thought I would be getting these problems)
As you can see, ALL classes defined in my code is public. So that is not my problem. The errors are generated on lines 126 and 127, as well as 160. The errors deal with the assignments of variables with my custom classes as type, and with my function returning a custom enum type. Help?
My psychic debugging sense tells me that you're not declaring a class as public
public class MyType
IF you want to make a public field of MyType, it's not enough to just type class MyType you have to make it public explicitly.
So when i try to use:
WebRequest request = WebRequest.Create("http://localhost:9998/API/GetGameById/" + ID.ToString());
WebResponse ws = request.GetResponse();
StreamReader responseStream = new StreamReader(ws.GetResponseStream());
string response = responseStream.ReadToEnd();
Game game;
using (MemoryStream Stream = new MemoryStream(UTF8Encoding.Default.GetBytes(response)))
{
XmlSerializer Serializer = new XmlSerializer(typeof(Game));
game = Serializer.Deserialize(Stream) as Game;
}
responseStream.Close();
return game;
the "game" that get's returned dose not have the same properties as the game in the xmlstring "response", it's like the :
game = Serializer.Deserialize(Stream) as Game;
creates a new instance of a game object instead of giving me the game at the specified ID
The "string response" locks like this:
<Game xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Gameboard i:nil="true" xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
<Id>1</Id>
<Players xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:int>1</a:int>
</Players>
<hsize>0</hsize>
<vsize>0</vsize>
<winner>0</winner>
</Game>
but the game at the return marker locks like this
<Game xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Gameboard i:nil="true" xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
<Id>0</Id>
<Players i:nil="true" xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
<hsize>0</hsize>
<vsize>0</vsize>
<winner>0</winner>
</Game>
Game class if it's of any help:
[DataContract(Namespace = "")]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Game
{
[DataMember]
int Id;
[DataMember]
int[] Players;
[DataMember]
int[] Gameboard;
[DataMember]
int hsize;
[DataMember]
int vsize;
[DataMember]
int winner = 0;
public Game()
{ }
public Game(int newgameID)
{
Id = ++newgameID;
}
public int GetSetId
{
get { return Id; }
set { Id = value; }
}
public int[] GetSetGameboard
{
get { return Gameboard; }
set { Gameboard = value; }
}
public int GetSetwinner
{
get { return winner; }
set { winner = value; }
}
public int[] GetPlayerList
{
get { return Players; }
}
public void AddPlayer()
{
int NewPlayer;
if (Players == null)
Players = new int[0];
List<int> temp = Players.ToList();
if (temp.Count == 0)
NewPlayer = 1;
else
{
NewPlayer = temp.Last();
NewPlayer++;
}
temp.Add(NewPlayer);
Players = temp.ToArray();
}
}
sorry if i gave you to much/little but this is my 3 or 4th post so i'm still learning just ask if your missing something
Thank you so much for taking your time and helping me out!
Have a great day!!
You may want to use a DataContractSerializer as demonstrated here instead of an XmlSerializer.
I tried with this extension method and it works a expected. The problem might be due to that the XmlSerializer does not work with private fields.
public static T DeserializeWithDataContractSerializer<T>(this string xml)
{
var dataContractSerializer = new DataContractSerializer(typeof(T));
using (var reader = new XmlTextReader( new StringReader(xml)))
{
return (T)dataContractSerializer.ReadObject(reader);
}
}
[Test]
public void GameTest()
{
string xml =
#" <Game xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"">
<Gameboard i:nil=""true"" xmlns:a=""http://schemas.microsoft.com/2003/10/Serialization/Arrays""/>
<Id>1</Id>
<Players xmlns:a=""http://schemas.microsoft.com/2003/10/Serialization/Arrays"">
<a:int>1</a:int>
</Players>
<hsize>0</hsize>
<vsize>0</vsize>
<winner>0</winner>
</Game>";
var game = xml.DeserializeWithDataContractSerializer<Game>();
Assert.AreEqual(1,game.GetSetId);
}
In the code that I'm working on, there are some properties that are serialized. All of them works fine as far as I can see, but one. Here's the code:
// Fields that the properties use.
private bool _useAlertColors = false;
private List<Int32> _colorArgb = new List<Int32>(new Int32[]{Color.White.ToArgb(), Color.Yellow.ToArgb(), Color.Red.ToArgb()});
// The one that does not work.
public List<Color> AlertColors
{
get
{
List<Color> alertColors = new List<Color>();
foreach (Int32 colorValue in _colorArgb)
{
alertColors.Add(Color.FromArgb(colorValue));
}
return alertColors;
}
set
{
// If there's any difference in colors
// then add the new color
for (int i = 0; i < _colorArgb.Count; i++)
{
if (_colorArgb[i] != value[i].ToArgb())
{
_colorArgb[i] = value[i].ToArgb();
HasChanged = true;
}
}
}
}
// One of those that work.
public bool UseAlertColors
{
get
{
return _useAlertColors;
}
set
{
if (_useAlertColors != value)
{
_useAlertColors = value;
HasChanged = true;
}
}
}
// Serializing method.
public bool Serialize(string filePath)
{
if (string.IsNullOrEmpty(filePath))
{
Logger.Log("Can't save settings, empty or null file path.");
return false;
}
FileStream fileStream = null;
try
{
fileStream = new FileStream(filePath, FileMode.Create);
FilePath = filePath;
System.Xml.Serialization.XmlSerializerFactory xmlSerializerFactory =
new XmlSerializerFactory();
System.Xml.Serialization.XmlSerializer xmlSerializer =
xmlSerializerFactory.CreateSerializer(typeof(Settings));
xmlSerializer.Serialize(fileStream, this);
Logger.Log("Settings have been saved successfully to the file " + filePath);
}
catch (ArgumentException argumentException)
{
Logger.Log("Error while saving the settings. " + argumentException.Message);
return false;
}
catch (IOException iOException)
{
Logger.Log("Error while saving the settings. " + iOException.Message);
return false;
}
finally
{
if (fileStream != null)
fileStream.Close();
}
return true;
}
After the serialization, this is what I end up with:
<UseAlertColors>true</UseAlertColors>
<AlertColors>
<Color />
<Color />
<Color />
</AlertColors>
What is wrong with the AlertColors property? Why is it not serialized?
Edit: I've changed the AlertColors property accordingly and it still is not working:
public List<int> AlertColors
{
get
{
return _colorArgb;
}
set
{
// If there's any difference in colors
// then add the new color
for (int i = 0; i < _colorArgb.Count; i++)
{
if (_colorArgb[i] != value[i])
{
_colorArgb[i] = value[i];
HasChanged = true;
}
}
}
}
What I get in the .xml file is this:
<AlertColors>
<int>-1</int>
<int>-8355840</int>
<int>-65536</int>
</AlertColors>
Which are the very first values that were set when the _colorArgb field was initialized. I can see the field change during the program execution, but when the covering property is serialized, it is serialized with the initial value of the underlying field.
What is causing the problem?
XMLSerializer only uses public properties of a class when serializing - The Color Class has none.
Heres a good example of how to get around it: http://www.codeproject.com/Articles/2309/NET-XML-Serialization-a-settings-class
Say I have a list of member, each of which is a custom object:
public class pail
{
public string milk;
public string water;
public string butter;
public string beer;
}
public class AddToPail()
{
private List<pail> _pailList = new List<pail>();
PSVM(String[] args)
{
for(int i = 0; i < 200; i++)
{
pail newPail = new Pail();
switch(i)
{
case 1:
{
newPail.milk = "This pail has milk";
}
break;
case 2:
{
newPail.butter = "This pail has butter";
}
break;
case 3:
{
newPail.water = "This pail has water";
}
break;
case 4:
{
newPail.beer = "This pail has beer";
}
break;
}
_pailList.Add(newPail);
}
foreach (pail thisPail in _pailList)
{
using (StreamWriter SW = new StreamWriter(#"C:\pail.txt")
{
if (!thisPail.milk.IsNullOrEmpty())
{
SW.WriteLine(thisPail.milk);
}
else if (!thisPail.butter.IsNullOrEmpty())
{
SW.WriteLine(thisPail.butter);
}
else if (!thisPail.beer.IsNullOrEmpty())
{
SW.WriteLine(thisPail.beer);
}
else if (!thisPail.water.IsNullOrEmpty())
{
SW.WriteLine(thisPail.water);
}
else
{
Console.Writeline("oops");
}
}
}
}
}
Say I want to set up a StreamWriter that only prints the true values without having to write a million if, else if, else statements... is there an easy way or library to do this in C#? I'm basically looking for a way to only print out true values in a neat, concise way. Does anyone have any advice as to how I should approach this?
Thank you very much!
EDIT
So the ultimate goal of this is that I have an object that has around 20 members. The object is automatically populated, and the populating script can leave some of the members empty. I'd like to be able to print the members in a CSV format, and not have to have 20 if statements to see if a particular member in the object has been instantiated before outputting via the streamwriter.
Edit 2
I changed my code to be a little closer to what I needed it to do. Sorry for the previous poor explanation.
I think you should refactor your program a little bit. For starters, I would use an enum for bucket contents:
public enum EBucketContents { Milk, Water, Butter, Beer };
Then, instead of having a list of booleans, you can use a dictionary:
var pail = Dictionary<EBucketContents,bool>();
Now it's a simple matter to only output the ones that are true:
foreach( var kvp in pail.Where( x => x.Value ) ) {
SW.WriteLine( "pail has " + kvp.Key.ToString().ToLower() )
}
If you just want to save some typing, use this extension method:
internal static class Extensions
{
public static void WriteLineIf(this TextWriter tw, bool condition, string text)
{
if (condition)
{
tw.WriteLine(text);
}
}
}
But it looks like only one of those bools can be true, since you're using else if blocks.
In that case, use and enum
internal enum Pail
{
Butter,
Milk,
Water,
Beer
}
Can you just use a Dictionary where the key is the field name and the value is the fields value. This way you don't need to check if the output is filled or not - you just output all fields
Your populating script can populate the dictionary keys only if they are set
Then your streamwriter can just go
foreach(KeyValuePair<string, string> kvp in fieldsDict)
sw.Write("Key: " + kvp.Key + ", Value: " + kvp.Value);
Or even just a list of string/or enum
e.g.
public class pail
{
public List<string> Fields = new List<string>();
}
public class AddToPail()
{
private List<pail> _pailList = new List<pail>();
PSVM(String[] args)
{
for(int i = 0; i < 200; i++)
{
pail newPail = new Pail();
switch(i)
{
case 1:
{
newPail.Fields.Add("This pail has milk");
}
break;
*** SNIP
Of course using a Dictionary could solve your problem , but I'm not really fond of this kind of solution, since it makes you lose some control over what you are putting in, e.g you could end up with a pail having airplanes... I'd refactor your code in something like this, trying to give every class its own responsabilities (BTW I don't like AddToPail as a class name, it's more a method name):
public class Pail
{
public string milk;
public string water;
public string butter;
public string beer;
private bool everythingEmpty = true;
public Pail(int i)
{
switch(i)
{
case 1:
{
milk = "This pail has milk";
everythingEmpty = false;
}
break;
case 2:
{
butter = "This pail has butter";
everythingEmpty = false;
}
break;
case 3:
{
water = "This pail has water";
everythingEmpty = false;
}
break;
case 4:
{
beer = "This pail has beer";
everythingEmpty = false;
}
break;
}
}
public void WriteToStream(StreamWriter SW)
{
if (everythingEmpty)
{
Console.Writeline("oops");
return;
}
WriteToStream(milk, SW);
WriteToStream(butter, SW);
WriteToStream(beer, SW);
WriteToStream(water, SW);
}
public static void WriteToStream(string content, StreamWriter SW)
{
if (!content.IsNullOrEmpty())
{
SW.WriteLine(content);
}
}
}
public class AddToPail()
{
private List<pail> _pailList = new List<pail>();
PSVM(String[] args)
{
for(int i = 0; i < 200; i++)
{
pail newPail = new Pail(i);
_pailList.Add(newPail);
}
foreach (pail thisPail in _pailList)
{
using (StreamWriter SW = new StreamWriter(#"C:\pail.txt")
{
thisPail.WriteToStream(SW);
}
}
}
}