XNA Creators Club Online
Page 1 of 1 (8 items)
Sort Posts: Previous Next

C# Serialization Help

Last post 22/02/2008 22:20 by finches. 7 replies.
  • 22/02/2008 17:20

    C# Serialization Help

    I know this isnt really XNA, but this is the only forum I have yet to post this problem at.  Out of all the sites i posted for help, nobody would respond or they didnt know what the problem is. 

    So here is my problem

    I am having a hard time serializing the XML file.  It Serializes and saves, but it wont serialize and load.  How can that happen?  If the program can successfully serialize it and save the file, it should be able to serialize and load the file right?  I have 2 classes that use serialization.

    public class CreditCard
    {
    #region Attributes
    private double limit, rate, balance;
    public double Limit
    {
    get { return this.limit; }
    set { if (value > 0) this.limit = value; }
    }
    public double Rate
    {
    get { return this.rate; }
    set { if (value > 0) this.rate = value; }
    }
    public double Balance
    {
    get { return this.balance; }
    set { this.balance = value; }
    }
    private string ccNumber, name;
    public string CCNumber
    {
    get { return "XXXXXXXXXX" + this.ccNumber.Substring(this.ccNumber.Length - 4, 4); }
    set { this.ccNumber = "XXXXXXXXXX" + value.Substring(value.Length - 4, 4); }
    }
    public string Name
    {
    get { return this.name; }
    set { this.name = value; }
    }
    private Collection<Payment> payments = new Collection<Payment>();
    public Collection<Payment> Payments
    {
    get { return payments as Collection<Payment>; }
    set { payments = value; }
    }
    DateTime lastUpdated;
    public DateTime LastUpdated
    {
    get { return this.lastUpdated; }
    set { this.lastUpdated = value; }
    }
    #endregion
    #region Constructors
    public CreditCard()
    : this("Unknown", "Unknown", 0.0, 0.0, 0.0)
    {
    }
    public CreditCard(string name, string ccNumber, double limit, double rate)
    : this(name, ccNumber, limit, rate, 0)
    {
    }
    public CreditCard(string name, string ccNumber, double limit, double rate, double balance)
    {
    this.name = name;
    this.lastUpdated = DateTime.Now;
    this.ccNumber = ccNumber;
    this.limit = limit;
    this.rate = rate;
    this.balance = balance;
    if (this.rate < 1)
    rate *= 100;
    }
    #endregion
    #region Methods
    public void update()
    {
    balance = 0;
    foreach (Payment p in payments)
    {
    //balance += ((float)p.Amount / 12.0f) * (this.rate / 100) * p.DaysSincePurchase();
    }
    }
    public void addPayment(Payment payment)
    {
    payments.Add(payment);
    }
    public void removePayment(Payment payment)
    {
    payments.Remove(payment);
    }
    public void increaseLimit(double inc)
    {
    if (inc > 0)
    limit += inc;
    else
    limit -= inc;
    }
    public void decreaseLimit(double dec)
    {
    if (dec > 0)
    limit -= dec;
    else
    limit += dec;
    }
    public override string ToString()
    {
    StringBuilder s = new StringBuilder();
    s.AppendLine("Name on Card: " + name);
    s.AppendLine("CC Number: " + ccNumber);
    s.AppendLine("Balance: " + balance);
    s.AppendLine("Limit: " + limit);
    s.AppendLine("Rate: " + rate);
    s.AppendLine("Payments: \n--------------");
    foreach(Payment p in payments)
    s.AppendLine(p.ToString());
    s.AppendLine("--------------");
    return s.ToString();
    }
    public void Save()
    {
    try
    {
    XmlSerializer serializer = new XmlSerializer(typeof(CreditCard));
    XmlTextWriter writer = new XmlTextWriter("CC_" + this.ccNumber.Substring(this.ccNumber.Length - 4, 4) + ".xml", null);
    serializer.Serialize(writer, this);
    }
    catch (IOException e) { }
    }
    public static CreditCard Load(string file)
    {
    XmlSerializer serlializer = new XmlSerializer(typeof(CreditCard));
    return (CreditCard)serlializer.Deserialize(File.OpenRead(file));
    }
    #endregion
    }

    public class Payment
    {
    #region Attributes
    DateTime purchaseDate;
    public DateTime PurchaseDate
    {
    get { return this.purchaseDate; }
    set { this.purchaseDate = value; }
    }
    double amount;
    public double Amount
    {
    get { return this.amount; }
    set { this.amount = value; }
    }
    string item, description;
    public string Item
    {
    get { return this.item; }
    set { this.item = value; }
    }
    public string Description
    {
    get { return this.description; }
    set { this.description = value; }
    }
    #endregion
    #region Constructors
    public Payment()
    : this(new DateTime(0, 0, 0), 0.0, "Not Set", "No Description")
    {

    }
    public Payment(DateTime purchaseDate, double amount, string item)
    : this(purchaseDate, amount, item, "No Discription")
    {
    }
    public Payment(DateTime purchaseDate, double amount, string item, string description)
    {
    this.purchaseDate = purchaseDate;
    this.amount = amount;
    this.item = item;
    this.description = description;
    }
    #endregion
    #region Methods
    public int DaysSincePurchase()
    {
    return DateTime.Now.Subtract(purchaseDate).Days;
    }
    public override string ToString()
    {
    StringBuilder s = new StringBuilder();
    s.AppendLine("Item: " + item);
    s.AppendLine("Description: " + description);
    s.AppendLine("Amount: " + amount.ToString());
    s.AppendLine("Date of Purchase: " + purchaseDate.ToString());
    return s.ToString();
    }
    #endregion
    }

    Here is the tricky thing, it works for my game that has a collection of players.  But it will not work for this.  And the game is a lot more complicated than this. 

    Finally. 
    I made payment as basic as I could, just a double variable and it still wouldnt work.  I redid them both very basic and it STILL wouldnt work.  When they are basic, it fails on creating the XmlSerializer instead of at the XmlWriter.  Any ideas please?

    I will post the error in a few minutes

    Again I know it really isnt XNA
  • 22/02/2008 17:53 In reply to

    Re: C# Serialization Help

    Because i've recently been dealing with serialization I figured I'd look at this.

    Without knowing what exactly the error is (I'm guessing an exception) I'm going to take a stab.

    XML Serialization requires a parameterless constructor, but I'm going to take a wild guess that you have not tested constructing your objects with the default ctor yet, have you?  new DateTime(0, 0, 0) is more than likely your culprit, leading you to believe its XML serialization when in fact it has nothing to do with that at all, instead an argument exception created by DateTime class.

     

    Edit: You're also going to want to close those file streams in Save and Load, otherwise GC isn't going to promptly take care of that for you.

  • 22/02/2008 18:57 In reply to

    Re: C# Serialization Help

    Yeah the error says month, day, year is not a valid DateTime format or something.  But new DateTime() allows you to pass only 3 ints for month day and year so why would it fail?
  • 22/02/2008 20:23 In reply to

    Re: C# Serialization Help

    Because 0, 0, 0 is not a valid date, so you can't construct it.  If you want to specify a null date use a nullable type like so:

    Nullable<DateTime> dt = null;   // OR: DateTime? dt = null;

    DateTime is a struct, that's why you need to use the Nullable generic structure.

    When your XML is attempting to deserialize, it constructs the empty object first before using your public setters.  Hence why that error occurs.

     

     

  • 22/02/2008 20:57 In reply to

    Re: C# Serialization Help

    DateTime has a constructor that accepts 3 integer values though.  So it generates a DateTime from the three values, it should generate a valid DateTime since its a constructor

    I think its DateTime(int year, int month, int day)
  • 22/02/2008 21:21 In reply to

    Re: C# Serialization Help

    Whiplash6:
    DateTime has a constructor that accepts 3 integer values though.  So it generates a DateTime from the three values, it should generate a valid DateTime since its a constructor

    I think its DateTime(int year, int month, int day)
    Yes, that is indeed the constructor. But like finches said, creating a new DateTime(0,0,0) is invalid. For reference: look at http://msdn2.microsoft.com/en-us/library/aa326682(VS.71).aspx The Deserializer is probably calling the DateTime constructor with these invalid arguments, which raises the exception.

     

  • 22/02/2008 21:36 In reply to

    Re: C# Serialization Help

    Ohhh OMG wow I am dumb lol.  I didnt even think to see that 0, 0, 0 where not accepted.  I have been using C# for 3 years now and I never made a mistake this dumb before. 

    Thanks a lot guys.  Sorry again that it wasnt XNA related. 


  • 22/02/2008 22:20 In reply to

    Re: C# Serialization Help

    Whiplash6:
    Ohhh OMG wow I am dumb lol.  I didnt even think to see that 0, 0, 0 where not accepted.  I have been using C# for 3 years now and I never made a mistake this dumb before. 

    Haha, hey, it happens to everyone....

    Unfortunately in your situation its kind of obscured by the reflection XmlSerializer is doing behind the scenes.  One of those situations where a test unit probably would have caught that up front.

Page 1 of 1 (8 items) Previous Next