I have a little problem that's been bugging my head for a few days. I am writing a kind of a manger tool for a virtual racing league. I want to save all my data into a single xml-file so that it can easily be accessed from several parties. However, because of the limitation of the xml-serializer, id have to make all my classes public. For that i have written an interface through which i want to convert my original managing objects (with all the functionality) into raw data containing objects for xml-serialization.
To be able to track who has created/changed something every relevant needs to hold a "ChangeNotification" field. For that i created a base class with these fields and from which my container classes are derived.
And now here comes the problem: If I serialize only a part of it it all works fine. But as soon as i serialize an Object which contains another Object derived from the same base, my "CreateChangeNotification" will only be present in the top Object.
I don't see why it's doing that as there are clearly two instances of it saved in the Objects, holding different values at the same time.
Sorry for the long code snippet, but that is what i needed to recreate the problem and it seems to happen everytime with this structure.
[Serializable()]
public class DataManagerXmlContainer<DataContainerType> : IDataManagerContainer
{
[XmlElement("Created")]
public ChangeNotificationXmlContainer created;
[XmlIgnore()]
public IChangeNotificationDataContainer Created { get => created; set => created = new ChangeNotificationXmlContainer(value); }
//[XmlElement("Changed")]
//public ChangeNotificationXmlContainer changed;
//[XmlIgnore()]
//public IChangeNotificationDataContainer LastChange { get => changed; set => changed = new ChangeNotificationXmlContainer(value); }
public DataManagerXmlContainer() { }
}
[Serializable()]
public class ReviewDataXmlContainer : DataManagerXmlContainer<IReviewDataContainer>, IReviewDataContainer
{
[XmlArray("CommentList")]
[XmlArrayItem("Comment")]
public List<ReviewCommentXmlContainer> comments = new List<ReviewCommentXmlContainer>();
[XmlIgnore()]
public ICollection<IReviewCommentDataContainer> Comments
{
get => comments.Cast<IReviewCommentDataContainer>().ToList();
set => comments = value.ToList().ConvertAll(x => new ReviewCommentXmlContainer(x));
}
public ReviewDataXmlContainer() { }
public ReviewDataXmlContainer(string authorID)
{
created = new ChangeNotificationXmlContainer(authorID, DateTime.Now);
}
public void AddComment(IReviewCommentDataContainer comment)
{
comments.Add(new ReviewCommentXmlContainer(comment));
}
}
[Serializable()]
public class ReviewCommentXmlContainer : DataManagerXmlContainer<IReviewCommentDataContainer>, IReviewCommentDataContainer
{
[XmlAttribute("author_id")]
public string AuthorAdminID { get; set; }
public string Text { get; set; }
public ReviewCommentXmlContainer() { }
public ReviewCommentXmlContainer(string authorID, string text)
{
created = new ChangeNotificationXmlContainer(authorID, DateTime.Now);
AuthorAdminID = authorID;
Text = text;
}
public ReviewCommentXmlContainer(IReviewCommentDataContainer dataContainer)
{
AuthorAdminID = dataContainer.AuthorAdminID;
Text = dataContainer.Text;
}
}
[Serializable()]
public class ChangeNotificationXmlContainer : IChangeNotificationDataContainer
{
[XmlAttribute("author_id")]
public string AuthorID { get; set; }
[XmlAttribute("time")]
public DateTime Time { get; set; }
public ChangeNotificationXmlContainer() { }
public ChangeNotificationXmlContainer(string id, DateTime time)
{
AuthorID = id;
Time = time;
}
public ChangeNotificationXmlContainer(IChangeNotificationDataContainer dataContainer)
{
AuthorID = dataContainer.AuthorID;
Time = dataContainer.Time;
}
}
public interface IChangeNotificationDataContainer
{
string AuthorID { get; set; }
DateTime Time { get; set; }
}
public interface IDataManagerContainer
{
IChangeNotificationDataContainer Created { get; set; }
}
public interface IReviewDataContainer : IDataManagerContainer
{
ICollection<IReviewCommentDataContainer> Comments { get; set; }
void AddComment(IReviewCommentDataContainer comment);
}
public interface IReviewCommentDataContainer : IDataManagerContainer
{
string AuthorAdminID { get; set; }
string Text { get; set; }
}
And the Program code:
class Program
{
static void Main(string[] args)
{
IReviewCommentDataContainer comment = new ReviewCommentXmlContainer("12345", "This is a test");
Task.Delay(1000).Wait();
ReviewDataXmlContainer review = new ReviewDataXmlContainer("23456");
review.AddComment(comment);
XmlSerializer serializer = new XmlSerializer(typeof(ReviewDataXmlContainer));
TextWriter writer = new StreamWriter("Test.xml");
serializer.Serialize(writer, review);
//Task.Delay(-1).Wait();
}
}
This is how my xml looks like:
<?xml version="1.0" encoding="utf-8"?>
<ReviewDataXmlContainer xmlns:xsi="http://www.w3.org/2001/XMLSchema instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Created author_id="23456" time="2018-11-16T06:56:16.5425819+01:00" />
<CommentList>
<Comment author_id="12345">
<Text>This is a test</Text>
</Comment>
</CommentList>
</ReviewDataXmlContainer>
As you can see the Create element of Comment is just missing.