I have a class Node something like this :
class Node {
IEnumerable<Node> inputs;
}
Which basicly defines a simple graph.
I want to serialize my graph to a human-readable form, so normally I'd say xml would be the way to go.
But XML wasn't made with cyclic dependencies in mind :)
So - what would be the best way to go for serialization of my graph ?
I can think of a few ways :
ditch XML, create my own format.
use XML, tag each node with a unique ID, store connection-lists separate from the Nodes and resolve after loading
But I think other people must have had this same problem before, so there might be some better options.
Does anyone know of a solid approach ?
For xml, I would go with the id approach (changing the DTO model such that it isn't cyclic).
Note that DataContractSerializer can support cyclic object graphs automatically by passing in true for the preserveObjectReferences option in the overloaded constructors; it won't be quite as simple as XmlSerializer output, but it will still be readable.
If you switch to WCF DataContractSerializer, you can preserve the Object References (in 3.5 SP 1 and later)
[DataContract(IsReference=true)]
Sowmy has a good write up here
Related
Using c#, I want to deserialize xml from various sources into objects of a common type. The XML will not have the same schema. Eg, in the following xml, /thingContainer/thing/name and widget/#title both would map to myClass.DisplayName.
Xml1:
<thingContainer>
<thing>
<name>MyName</name>
</thing>
</thingContainer>
Xml2:
<widget title="myTitle" />
So, I can't mark up my class with [XmlElement], since it will be different depending on the source of my xml. Is there some trick I can do with inheritance or some helper class that will enable me to easily deserialize xml from different sources? Is there some easy way to map class fields to xpaths?
Of course, if I have to, I'll parse and manually deserialize the xml... but what fun is that?
Two thoughts that immediately spring to mind:
Use XSLT to transform the original XML into an interim format that matches your object model (a very popular approach, though personally I despise XSL)
Create interim object models to deserialize to, then map them to your final object model.
There's probably some XmlElement hackery possible, but it seems like it would be a messy approach.
I think you have two options here:
Implement IXmlSerializable for your class and deserialize taking into account the structure of your XML
Just use LINQ to XML to parse the XML and create an instance of your class. This is the approach I would pick (having gone through the first choice myself and not liking it)
I'm currently using XmlSerializer to, surprisingly enough :), handle de/serialization of my data structures - I find it wonderfully simple to use, but at the cost of flexibility. At the moment, I'm using it for a tree-based structure; since XmlSerializer doesn't handle cyclic structures, I've added [XmlIgnore] to my Parent property, and do a post-deserialization iteration over the tree to fix up node parents.
Is there a better way to handle this using XmlSerializer, or would it be better to rewrite the code using XmlReader/XmlWriter? I suppose implementing IXmlSerializable would work, but it seems like a fair amount of work, while still retaining the cons of XmlSerializer.
The current post-deserialization step is OK, but I'm adding a data structure that has to be serialized to a separate XML file: basically a flat list of items that need a Parent property referencing a node from the previous tree structure. This would require yet a post-deserialization step, as well as keeping both a Parent attribute as well as as ParentId (or some trickery) in the new data structure.
So, any smart (and non-fragile) ideas? Or XmlReader/XmlWriter it is?
Solution
DataContractSerializer turned out to be a pretty decent solution, with pretty much the same simplicity as XmlSerializer. I opted not to use the automatic cycle handling but instead defining and OnDeserialized decorated method to handle setting the parent node; that way, the generated XML is standard-conforming.
One thing that confused me for a while was that I got crashes on some properties after deserializing, with the backing members set to null - couldn't figure out how this was possible since the backing members were definitely initialized in all possible constructors. Debugging showed constructors were never called, and after some googling I found this SO post with an explanation.
You could try binary serialization (BinarySerializer or DataContractSerializer), which I think handles cyclic graphs somewhat better, at the cost of not having a human-readable representation of the data. Alternatively, you can try the SoapFormatter as detailed here.
Use DataContractSerializer. Mark your classes with [DataContract(IsReference = true)].
If I am dealing with several standard xml formats what would be the best practice way of encapsulating them in C# 3.5? I'd like to end up with something similar to the System.ServiceModel.Syndication namespace.
A class that encapsulates the ADF 1.0 XML standard would be one example. It has the main XML root node, 6 child elements, 4 of which are required IIRC, several required and optional elements and attributes further down the tree. I'd like the class to create, at a minimum, the XML for all the required pieces all the way up to a full XML representation. (Make sense).
With LINQ 4 XML and extension classes, etc, etc, there has to be some ideas on quickly generating a class structure for use. Yes? No? :)
Am not sure if I gave enough details to get one correct answer but am willing to entertain ideas right now.
TIA
XML serialization seems a good approach. You could even use xsd.exe to generate the classes automatically...
EDIT
Note that the class names generated by the tool are usually not very convenient, so you might want to rename them. You might also want to change arrays of T to List<T>, so that you can easily add items where needed.
Assuming the class for the root element is named ADF, you can load an ADF document as follows :
ADF adf = null;
XmlSerializer xs = new XmlSerializer(typeof(ADF));
using (XmlReader reader = XmlReader.Create(fileName))
{
adf = (ADF)xs.Deserialize(reader);
}
And to save it :
ADF adf = ...; // create or modify your document
...
XmlSerializer xs = new XmlSerializer(typeof(ADF));
using (XmlWriter writer = XmlWriter.Create(fileName))
{
xs.Serialize(writer, adf);
}
Why not just follow the pattern of the SyndicationFeed object in the Syndication namespace? Create a class that takes in a Uri to the xml document or just takes in the document fragment.
Then parse the document based on your standards (this parsing can be done using LinqToXml if you wanted to, though regEx might be faster if you are comfortable with them). Throw exceptions or track errors appropriately when the document doesn't pass the specification rules.
If the document passes the parse step then break the pieces of the document out into public getter properties of your object. Then return the fully hydrated object back to the consumer for use
Seems pretty straight forward to me. Is that what you are after or are you looking for something more than this?
I have some very similar XML structures which are in fact quite distinct, but it appears that XmlSerializer.Deserialize is very "forgiving" and will go out of its way to take XML and deserialize out into a strongly typed object I created from the source XSDs. Is there any way to make it more strict or do some type of deeper validation?
// Locals
var serializer = new XmlSerializer(typeof(SomeCustomType));
// Set
var someInstance = serializer.Deserialize(new StringReader(xmlString.ToString()))
#Jeff Because the root nodes are similar it will deserialize into completely different objects. Imagine that you have a house, car and boat and they all share a base root node called item with a few attributes. Even though sub-nodes are invalid and unshared it seems to overlook and forgive that.
#Will I don't want to validate against the XSD. I want to somehow cause the Deserializer to see that the data it has shouldn't be shoe-horned into the wrong Object type.
The problem was that the XML input was incorrect.
I once used validating reader to validate XML against schema as I read it into the deserializer.
I'm writing a document-based client application and I need a DOM or WPF-like, but non-visual model that:
Is a tree composed of elements
Can accept an unlimited number of custom properties that
get/set any CLR type, including collections.
Can inherit their values from their parent
Can inherit their default values from an ancestor
Can be derived/calculated from other properties, ancestors, or descendants
Support event bubbling / tunneling
There will be a core set of properties but other plugins may add their own or even create custom documents
Supports full inspection by the owning document in order to persist the tree and attributes in an XML format.
I realize that's a tall order but I was really hoping there would be something out there to help me get started. Unfortunately WPF DependencyObjects are too closed, proprietary, and coupled to WPF to be of any use as a document model. My needs also have a strong resemblance to the HTML DOM but I haven't been able to find any clean DOM implementations that could be decoupled from HTML or ported to .NET.
My current platform is .NET/C# but if anyone knows of anything that might be useful for inspiration or embedding, regardless of the platform, I'd love to know.
I don't think that it meets all of the requirements you specified, but have you considered working with an XML DOM (as opposed to an HTML DOM)? You can create an XML document programmatically in .NET and manipulate it using DOM methods and properties, and also do things like XPath queries. Check out .NET's XmlDocument object. This might be a reasonable starting point.
Maybe XMLBeans could help.
Eclipse EMF might help, but it might also be overkill for you. IMHO good designed language should make such a task extremely easy...
Netbeans platform pretty much does exactly what you want.
Are you looking for advice for an object model? How about:
// C#-ish code that probably doesn't compile
class Element {
public object GetAttribute(string attribute) {
if (this.Attributes.HasKey(attribute))
return this.Attributes[attribute];
else
return this.Parent.GetAttribute(attribute);
}
private IDictionary<string,object> Attributes;
private Element Parent;
private IList<Element> Children; // maybe not needed
// etc.
}
and go from there?