I am currently working on this application(C#,WPF,LINQ2XML,.NET 4.0) that displays details for 'Animals'. An example of this would be the application displaying the types of Animals such as 'Birds','Mammals','Reptiles'. For each type of Animal, I will have sub-entries such as for 'Birds' I will have sub-entries like 'Sparrow','Hawk'; for 'Reptiles', I will have 'Alligators', 'Python'..etc..etc. The user will have the option to add comments for each of these sub-entries. An example would be for the sub-entry 'Sparrow', I will have an option to 'Add Comments'. Clicking on 'Add Comments' will pull up a textbox where the user can enter his or her comments for 'sparrow'. The user can insert multiple comments for a sub-entry. The user can have 1,2,3....n comments for 'Sparrow'. This will just entail clicking on 'Add Comments' multiple times.
The data is preloaded with information stored in XML files. I have separate XMLs for each Animal such as Birds.xml, Mammals.xml, Reptiles.xml. Each of these will have information regarding the sub-entries. Birds.xml will have XML fragments for 'Sparrow' and 'Hawk'.
I am using Linq2Xml to extract the information necessary to populate my animal objects(Model) which in turn are bound to the Presenter(I am using the Model-View-Presenter pattern) which is fed to the XAML.
I am successfully able to display the information from my XML in the view. The problem is with the 'Comments'.
There are two things that I need to achieve here:
Write all the comments added to a separate XML file (AnimalComments.xml) where I can store all the comments that have been added for all the sub-entries.
In case of an application failure, I would like this same XML file(AnimalComments.xml) to pre-populate all the comments that I entered before my application crashed.
In essence I am trying to serialize the state onto the disk but in reality I don't want the entire object graph to persist on the disk since I think I am going to add the feature of writing/adding to the AnimalComments.xml file whenever a comment is typed for a sub-entry and the focus is changed to some other sub-entry.
I was wondering if the collective wisdom of SO can help me with some elegant design guidance here to accumulate all the Comments added and persist them onto a disk in such a way that it can be used by the application later for a restore or to present in a human readable format. Any solutions requiring the use of an DBMS would not be pertinent in this situation since it is part of the requirement to store any data associated with the application on the local file system.
As Drake suggested below, there are ways to maintain the references to the Animals using some sort of Primary key but I am interested in how this should be tackled from an 开发者_C百科Object Oriented standpoint or if there are some prominent patterns that tackle this sort of a situuation.
Thanks
I have created the classes below. Please copy the code and pass to the editor !
The animals.cs
using System.Xml.Serialization;
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://tempuri.org/XMLSchema.xsd")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.org/XMLSchema.xsd", IsNullable=false)]
public partial class Animals {
private Animal[] animalField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Animal")]
public Animal[] Animal {
get {
return this.animalField;
}
set {
this.animalField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://tempuri.org/XMLSchema.xsd")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.org/XMLSchema.xsd", IsNullable=false)]
public partial class Animal {
private string nameField;
private int idField;
private bool idFieldSpecified;
/// <remarks/>
public string Name {
get {
return this.nameField;
}
set {
this.nameField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public int ID {
get {
return this.idField;
}
set {
this.idField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool IDSpecified {
get {
return this.idFieldSpecified;
}
set {
this.idFieldSpecified = value;
}
}
}
The AnimalComments.cs
using System.Xml.Serialization;
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://tempuri.org/AnimalComments.xsd")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.org/AnimalComments.xsd", IsNullable=false)]
public partial class Animals {
private Animal[] animalField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Animal")]
public Animal[] Animal {
get {
return this.animalField;
}
set {
this.animalField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://tempuri.org/AnimalComments.xsd")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.org/AnimalComments.xsd", IsNullable=false)]
public partial class Animal {
private Comments commentsField;
private int idField;
private bool idFieldSpecified;
/// <remarks/>
public Comments Comments {
get {
return this.commentsField;
}
set {
this.commentsField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public int ID {
get {
return this.idField;
}
set {
this.idField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool IDSpecified {
get {
return this.idFieldSpecified;
}
set {
this.idFieldSpecified = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://tempuri.org/AnimalComments.xsd")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.org/AnimalComments.xsd", IsNullable=false)]
public partial class Comments {
private Comment[] commentField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Comment")]
public Comment[] Comment {
get {
return this.commentField;
}
set {
this.commentField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://tempuri.org/AnimalComments.xsd")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.org/AnimalComments.xsd", IsNullable=false)]
public partial class Comment {
private string contentField;
private int commentIDField;
private bool commentIDFieldSpecified;
/// <remarks/>
public string Content {
get {
return this.contentField;
}
set {
this.contentField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public int CommentID {
get {
return this.commentIDField;
}
set {
this.commentIDField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool CommentIDSpecified {
get {
return this.commentIDFieldSpecified;
}
set {
this.commentIDFieldSpecified = value;
}
}
}
Cheers.
In my opinions, your issues are only the matter of how we will organize data structure. So let's have a look at each issue:
1.
Write all the comments added to a separate XML file (AnimalComments.xml) where I can store all the comments that have been added for all the sub-entries
I propose that in the animals.xml file you add an unique ID field for each animal , and in the animals file we use the ID as the foreign key to reference comments back to animals.
For instance, we have a birds.xml like that
<?xml version="1.0" encoding="utf-8"?>
<Animals>
<Animal ID="1">
<Name>Jack Sparrow</Name>
</Animal>
<Animal ID="2">
<Name>Black Hawk</Name>
</Animal >
</Animals>
Then the animalcomments.xml file should be like that:
<?xml version="1.0" encoding="utf-8"?>
<Animals>
<Animal ID="1">
<Comments>
<Comment CommentID="1">
<Content>Hello world</Content>
</Comment>
<Comment CommentID="2">
<Content>Hello world 2</Content>
</Comment>
</Comments>
</Animal>
<Animal ID="2">
<Comments>
<Comment CommentID="1">
<Content>Hello world</Content>
</Comment>
<Comment CommentID="2">
<Content>Hello world 2</Content>
</Comment>
</Comments>
</Animal>
</Animals>
So you can generate the code based on that data structure, reading and writing to each element of the animalcomments.xml file.
2.
In case of an application failure, I would like this same XML file(AnimalComments.xml) to pre-populate all the comments that I entered before my application crashed.
In your
HandleUnhandledException()
method, saving all your comments before terminating the program. Once the program is reloaded, you can get all your comments back.
Hope this help.
精彩评论