This is for a web project so i have several classes that inherit from Web.UI.
I only want to serialize very particular properties (basically, only local properties)
I'm aware of the XMLIgnore property that can be placed on a property to ignore items, but this won't work in my context since that would require modifying a bunch of stuff that i really don't want to modify (and probably can't).
So how do i tell the xml serializer to ignore everything except for X and Y or tell it to seralize just X and Y?
i could just create my own xml in a string builder or something and if that's the only way, so be it. however i'm looking for a method that will employ the built in XML stuff.
Thanks
For Custom Serialization, you can derive your class from ISerializable Interface and provide Custom Serialization accordingly
Why don't you implement IXmlSerializable?
You could put some hack into it and simply tear stuff out of the XML after it comes back.
It's a terrible idea compared to XMLIgnore, which is the correct solution, but you could certainly pull up the XML, spin through it, and remove whatever you don't want to see.
Sometimes terrible ideas are the best ones.
Related
whenever I try to serialize an object that has an IEnumerable collection I get a big dirty error telling me it can't serialize it because it's an interface. Now I get why it's happening but it raises some other questions for me. Like if I intend on having collections within my objects AND I want to serialize them do I need to resort to
Using List<>, CollectionBase, ReadOnlyCollectionBase in my objects.
Making my objects implement the IXmlSerializable interface.
Decorating my classes with horrible attributes.
Writing my own serializer.
What is the best practice way to go?
Speaking as a serializer author, I know exactly why it gets very hard to robustly work just from IEnumerable<T>, especially for "get-only" properties. You might try IList<T> (although it wouldn't amaze me if it wants a concrete type such as List<T>/T[]), but I suspect the real problem here is that you trying to use one model to do two things, and are unhappy at having to compromise to do it.
Fine: if you don't want to compromise your domain model, write a separate DTO model that is used for serialization, and just map between them. This is usually trivial, and will allow the serializer and the domain model to each excel at their one job. It will also help immensely when you need to "version" the system or introduce a different serializer (JSON, protobuf, etc).
Re your bullets:
I suspect any concrete list type (even your own) with Add etc will work
I don't recommend that to anyone - it is painful to do reliably
nothing ugly about attributes; again, I suspect your complaint is about attributing your domain model - so: fine, don't do that - have a separate model; you can actually do all this at runtime, but it is much more work (see XmlAttributeOverrides, but watch out for leaking assemblies if you do this)
don't underestimate how much work that is; the basics - seductively easy; but the non-trivial scenarios can be brutal
For use interface or derivade classes you MUST use the XmlSerializer(Type type, Type[] extraTypes) constructor.
In extraTypes you MUST include all possible classes which can implement the interfaces in your classes.
I have a lot of properties to serialize using XmlSerializer. I need to tag each (simple) property with [XmlAttribute] to make the output a little shorter. I'm wondering if there is an easier way to do it. Is there a way to make it as a default for a class, so that all simple type properties will be serialized as attribute instead of element?
No, basically. Well, you could do the work at runtime using XmlAttributeOverrides, inspecting your types in code and setting the attributes appropriately, then making sure you cache the serializer (if you don't cache when using XmlAttributeOverrides you leak memory, as the generated assemblies aren't collected). But that sounds like more work.
Re making the output shorter; xml compresses with GZip or Deflate very nicely...
Of course, if you don't need xml, but just need the data serialized somehow, there are other options.
You can create code snippets.
Create one for properties with the attribute already set, and use it when writing them.
I'm learning about serialization in C# and I have the basics down, but now I am trying something a little more complicated and I'm looking for some pointers on best practice (I can achieve what I want, I just want to know the 'right'/easiest/least code/most robust method of doing it).
I have a racing track which is made up of sections. Each section type inherits from a common TrackSection class. The TrackSection class holds a lot of data on geometry and other things that I don't want to save out and it needs some context information when the constructor is called, so I have implemented the ISerializable interface and provided my own methods to handle (de)serialization. The classes that inherit from TrackSection are a lot simpler, and I would be happy for all their fields to be serialized automatically, but I assume that since the base class is ISerializable they probably need to do it manually as well (I have added the deserialization constructor and call the base class's deserialization constructor in each). When it comes to serializing though I'm not sure what to do, I would have expected ISerializable's GetObjectData() method to be virtual so I could extend the serialization in sub-classes. Do I simply need to implement my own virtual method that is called from the base class's GetObjectData(), or am I going about this all wrong?
As I say, I have it working but any better solution or any general tips about what I'm doing would be much appreciated, as I can't help but feel my solution is a little more complicated than it needs to be. Thanks.
Unless you're doing something where you need to implement ISerializable, you could, instead just mark the class with the Serializable attribute and mark the fields that you don't want serialized as NonSerialized
What is a better approach to serialize custom class: using XMLSerializer or BinarryFormatter and [Serializable] attribute on class?
It's not possible to answer this, without knowing how you will use the resulting file, and the lifetime of it.
The decision is based on the fact that it is harder to "upgrade" the binary format. If your object model changes, it won't deserialise correctly. But if you've implemented a custom XML serialisation/deserialisation, then you can handle the "new" cases appropriately, and life will be good.
So decide more about how you will use it, who you are sharing information with, and what the possible changes to the model are.
FWIW, I sometimes use both types of serialisation in a given project.
That really depends on how you use the serialized class. If you want to pass it to other programs or want to easily debug it, use XML (but mind that XMLSerializer might produce non-compliant XML output, like multiple root elements).
In all other cases, you can use the binary formatter. But note that XML is more suitable if you change the class later - you can use XMLIgnore and the like to keep the XML format intact.
The decision will sometimes also be made for you based on what the serialized output will be used for - while you could expose a WebService to take a binary array that is a binary serialized item, you couldn't utilize the web service easily from anything but .Net (and the end client would probably need a reference to the type).
Using XML means that the service could be exposed to any end client regardless of the platform/environment on the end client
I've got a program that picks up some code from script files and compiles it.
And It works fine.
The problem is: in the scripts I declare a couple of classes and I want to serialize them.
Obviously the C# serializer (xml and binary) doesn't like to serialize and the de-serialize object defined in a in-memory assembly.
I prefer to don't leave the in-memory assembly so i'm looking for another way of serializing, but in case, is possible to build assembly in memory and eventually write it on file ?
You could always write your own ToXml function using reflection to write out your property data to a string. Then your object would deserialize itself.
Just a thought.
If you want to create assemblies dynamically look into IL emitting via reflection. Here is a good article to get you started.
So just to clarify, are you asking how you can serialize a type if it hasn't got the [Serializable] attribute applied?
One solution is to use the WCF Data Contract Serializer: http://msdn.microsoft.com/en-us/library/ms731923.aspx.
Obviously this will only work if you can target .Net 3.0 or higher.
Alternately you can implement an ISerializationSurrogate. Jeffrey Richter has a great introduction at http://msdn.microsoft.com/en-us/magazine/cc188950.aspx.
I would avoid all built-in serialization whenever possible, both are badly broken. For example, XML serialization doesn't support dictionaries and normal serialization/SOAP doesn't support generics. And both have versioning issues.
It is time consuming, but createing ToXML and FromXML methods is probably to most effective way to go.
Hava a look at here for custom serialisers, which is a sample for dictionary XML serializing
I'm slightly confused by the statement that the XmlSerializer can't serialize dynamically generated types. The XmlSerializer generates it's own serialization code dynamically as well during construction so there should be no issue with it serializing your type.
You may need to decorate your dynamic classes with the appropriate attributes, depending on what you are generating (like derived classes), but there shouldn't be any issue with using the XmlSerializer in the situation you described.
If you could post details about the issues the XmlSerializer is giving you I can help you work out what the problem is.
Also, I'm of the belief that auto-generating code is in general a blessing. All to often have I had to go back into a class to fix one or all of the copy/paste/save/load functions, just because someone forgot to update them when adding a new variable. Save/Load code is boiler plate code. Let the computers write it.