Tuesday, February 14, 2012

deserializing a collection which implements collectionbase

I had a post very similar to this a week or so ago and I received a couple good solutions ... unfortunately, I forgot to mention 1 point that apparently makes a big enough difference so that the solution given won't work. Here's what I originally posted
(and below that is more info):
I'm writing a class in C# ...
I have a collection calls Reports made up of Report objects. I'm trying to deserialize an XML file that looks like :
<Reports>
<Report>
<Title>some title</Title>
<Notes> some notes </Notes>
</Report>
<Report>
blah blah blah
</Report>
</Reports>
I want to be able to deserialize the file in the Reports collection constructor and build the Report objects on the fly. The only examples I've been able to find read the entire XML file outside of the class (which works fine in my test console app), but
I want to be able to be able to dynamically build everything inside the collection class. Do I need to parse through the XML file and got to each <Report> tag and deserialize one Report at a time (and use "this.Add(newReport)")? How can parse the file
like that and pass just that info into the deserialize method? I haven't used XPath, so if I need that, an example would really help.
NOW..........................
what I failed to mention was that my Reports collection implements CollectionBase and now I recieve the following error: "XML attributes may not be specified for the type TestCore.Reports"
I remove the CollectionBase implementation and it works. I've found several websites saying that I can deserialize a class implementing CollectionBase, but I haven't found any examples or help as to what I'm doing wrong. Here's what I have for the colle
ction class using the solution I received in my earlier post (if need be I can post more of my code):
[System.Xml.Serialization.XmlRoot("Reports", Namespace="", IsNullable=false)]
[System.Xml.Serialization.XmlType("Reports", Namespace="")]
public class Reports : CollectionBase
{
[System.Xml.Serialization.XmlElementAttribute "Report",Form=System.Xml.Schema.XmlSchemaForm.Unqu alified)]
public Report[] Items1;
public Reports() {}
public Reports(string path)
{
Reports temp= Reports.CreateFromString(path);
Items1= temp.Items1; // shallow copy of array. Would need to do this for each field in the RC type
// "temp" now goes out of scope but the Items array gets referenced by "this"
}
public static Reports CreateFromString(string xml1)
{
// could parameterize this with a filename, a stream, a string,whatever
XmlSerializer s1 = new XmlSerializer(typeof(Reports));
// slurp it in: deserialize the original XML into a value
System.IO.StringReader sr= new System.IO.StringReader(xml1);
Reports rc= (Reports) s1.Deserialize(new System.Xml.XmlTextReader(sr));
return rc;
}
public int Add(Report report)
{
return List.Add(report);
}
public Report this[int index]
{
get
{
return((Report)List[index]);
}
set
{
List[index] = value;
}
}
}
You need to remove the attributes from the class that derives from
CollectionBase.
The side effect of this is that your collection will now serialize as
<ArrayOfReport>
<Report>...</Report>
...
</ArrayOfReport>
Rather than what you wanted, which was:
<Reports>
<Report>...</Report>
...
</Reports>
To work around this you can specify an XmlRootAttribute() in the serializer.
See here for an example that combines the answer to your 2 most recent asks
(self-instantiation and serializing a CollectionBase):
http://www.winisp.net/cheeso/srcview...lectionBase.cs
Note that the copy in the parameterized constructor is different in this
code that in the prior code, because the "Items1" field is not used. So
here you gotta iterate to do the copy.
-D
Dino Chiesa
Microsoft Developer Division
d i n o c h @. OmitThis . m i c r o s o f t . c o m
"Greg" <Greg@.discussions.microsoft.com> wrote in message
news:59CCBFD6-29FB-40A1-9B9D-09F6A98A983E@.microsoft.com...
> I had a post very similar to this a week or so ago and I received a couple
good solutions ... unfortunately, I forgot to mention 1 point that
apparently makes a big enough difference so that the solution given won't
work. Here's what I originally posted (and below that is more info):
> I'm writing a class in C# ...
> I have a collection calls Reports made up of Report objects. I'm trying
to deserialize an XML file that looks like :
> <Reports>
> <Report>
> <Title>some title</Title>
> <Notes> some notes </Notes>
> </Report>
> <Report>
> blah blah blah
> </Report>
> </Reports>
> I want to be able to deserialize the file in the Reports collection
constructor and build the Report objects on the fly. The only examples I've
been able to find read the entire XML file outside of the class (which works
fine in my test console app), but I want to be able to be able to
dynamically build everything inside the collection class. Do I need to
parse through the XML file and got to each <Report> tag and deserialize one
Report at a time (and use "this.Add(newReport)")? How can parse the file
like that and pass just that info into the deserialize method? I haven't
used XPath, so if I need that, an example would really help.
> NOW..........................
> what I failed to mention was that my Reports collection implements
CollectionBase and now I recieve the following error: "XML attributes may
not be specified for the type TestCore.Reports"
> I remove the CollectionBase implementation and it works. I've found
several websites saying that I can deserialize a class implementing
CollectionBase, but I haven't found any examples or help as to what I'm
doing wrong. Here's what I have for the collection class using the solution
I received in my earlier post (if need be I can post more of my code):
> [System.Xml.Serialization.XmlRoot("Reports", Namespace="",
IsNullable=false)]
> [System.Xml.Serialization.XmlType("Reports", Namespace="")]
> public class Reports : CollectionBase
> {
> [System.Xml.Serialization.XmlElementAttribute
"Report",Form=System.Xml.Schema.XmlSchemaForm.Unqu alified)]
> public Report[] Items1;
> public Reports() {}
> public Reports(string path)
> {
> Reports temp= Reports.CreateFromString(path);
> Items1= temp.Items1; // shallow copy of array. Would need to do
this for each field in the RC type
> // "temp" now goes out of scope but the Items array gets
referenced by "this"
> }
> public static Reports CreateFromString(string xml1)
> {
> // could parameterize this with a filename, a stream, a string,
whatever
> XmlSerializer s1 = new XmlSerializer(typeof(Reports));
> // slurp it in: deserialize the original XML into a value
> System.IO.StringReader sr= new System.IO.StringReader(xml1);
> Reports rc= (Reports) s1.Deserialize(new
System.Xml.XmlTextReader(sr));
> return rc;
> }
> public int Add(Report report)
> {
> return List.Add(report);
> }
> public Report this[int index]
> {
> get
> {
> return((Report)List[index]);
> }
> set
> {
> List[index] = value;
> }
> }
> }
>

No comments:

Post a Comment