views:

193

answers:

5

I work as a web developer with a web designer and we usually do like this : - I create the system , I generate some Xml files - the designer display the xml files with xslt

Nothing new.

My problem is that I use Xml Serialization to create my xml files, but I never use Deserialization. So I'd like to know if there is a way to avoid fix like these :

  • empty setter for my property

  • empty parameter-less constructor

  • implement IXmlSerializable and throw "notimplementedexception" on deserialization

  • do a copy of the class with public fields

+4  A: 

Ok mis-read your question first time around! Pretty sure there is no way to avoid this. There has to be a parameterless constructor and you can't serialize readonly properties. I think your only other option is DataContractSerializer.

James
It seems like a good solution I'll have a deeper look thanks.
remi bourgarel
The transition is actually pretty smooth (I found myself anyway). DataContractSerialier has a lot more features and less restrictions.
James
Arf ... dmn it ! DataContractAttribute is not available in .net 2.0 ... sry I didn't say it in my question. I think i'll have to use one the dirty solutions. Thanks anyway
remi bourgarel
Is there any particular reason you can't upgrade to at least 3.0?
James
DataContractSerializer doesn't XML Attributes either. You can use IXmlSerializable to build custom serailziers. And if you can use LINQ2XML you can even skip all the fun from creating classes (I use LINQ2XML with RESTful WCF and XSLT for a custom photo gallery.)
Matthew Whited
@Matthew +1 failed to mention that it doesn't support attributes out the box. However, as you have commented there are ways of doing this. Here is another way...http://www.lordzoltan.org/blog/post/Serializing-to-attributes-in-WCF-with-DataContractSerializer.aspx
James
A: 
class Preferences
{
    private const string filePreferences = "preferences.xml";

    public Preferences() { }

    public static Preferences Load()
    {
        Preferences pref = null;
        if (File.Exists(Preferences.FileFullPath))
        {
            var serializer = new System.Xml.Serialization.XmlSerializer(typeof(Preferences));
            using (var xmlReader = new System.Xml.XmlTextReader(Preferences.FileFullPath))
            {
                if (serializer.CanDeserialize(xmlReader))
                {
                    pref = serializer.Deserialize(xmlReader) as Preferences;
                }
            }
        }
        return ((pref == null) ? new Preferences() : pref);
    }

    public void Save()
    {
        var preferencesFile = FileFullPath;
        var preferencesFolder = Directory.GetParent(preferencesFile).FullName;

        using (var fileStream = new FileStream(preferencesFile, FileMode.Create))
        {
            new System.Xml.Serialization.XmlSerializer(typeof(Preferences)).Serialize(fileStream, this);
        }
    }
}
abatishchev
My problem here is not how to serializae/deserialize (I know how to type "c# xml serialization" in google). But I'd like to know how to serialize without fixing deserialization constraints
remi bourgarel
@abatishchev: the XML Serializer pays no attention to `[Serializable]`.
John Saunders
@John Saunders: Yeap, you're right.
abatishchev
+1  A: 

http://blogs.mastronardi.be/Sandro/2007/08/22/CustomXMLSerializerBasedOnReflectionForSerializingPrivateVariables.aspx

This article describes creating a custom XML serialiser so you can serialise private fields - it may take a little bit of moulding to the form that you want, but it's easier than it looks (honest!) and it's a good start to writing your own serialiser / deserialiser that will serialise exactly what you want - and doesn't care about parameterless constructors or writeable properties.

The only other solution I can think of is to make a wrapper class for every serialisable class - but I don't know how good that would be in the long run. I just get the impression it's not good.

pete the pagan-gerbil
You can serialize private fields using DataContractSerializer.
James
Nice little article except the guy claims that the IXmlSerializable interface is undocumented and Microsoft says it's for internal use only. Has this actually ever been the case? It's certainly documented and I see no claims from Microsoft about being internal use only.
Jesse C. Slicer
I said that I didn't want to implements IXmlSerializable : it's a lot of code and I don't really like to manipulate XmlReader/Writer. And with this method I think we need a parameter-less constructor (not sure 100%)
remi bourgarel
I used it as a starting point myself to make a serialising class without IXmlSerializable. I was only really pointing to it as the starting point to using reflection, if you wanted to write your own serializing class.But if you don't want to use an XmlReader/Writer or roll your own serializer, this way might be too hard for you.@James: Thanks for the tip, I never found that trying to solve my problem!@Jesse C. Slicer: I have no idea. I was looking for reflection code related to serializers, I didn't pay much attention to the rest.
pete the pagan-gerbil
A: 

Ok now i understand it. I don't think there can be any way to do it with XMLSerialization. XMLSerialization need these information to re-populate the object. It does not know that some user never deserialize data. You might have to write some code to generate XML for your objects.

cornerback84
A: 

I know you don't want to add a parameterless constructor nor setters, but that's the only way to go with using the XmlSerializer. The good news is the parameterless constructor can be private and the setters can be empty and serialization will work. See thus:

namespace Aesop.Dto
{
    using System;
    using System.Xml.Serialization;

    /// <summary>
    /// Represents an Organization ID/Name combination.
    /// </summary>
    [Serializable]
    public sealed class Org
    {
        /// <summary>
        /// The organization's name.
        /// </summary>
        private readonly string name;

        /// <summary>
        /// The organization's ID.
        /// </summary>
        private readonly int id;

        /// <summary>
        /// Initializes a new instance of the <see cref="Org"/> class.
        /// </summary>
        /// <param name="name">The organization's name.</param>
        /// <param name="id">The organization's ID.</param>
        public Org(string name, int id)
        {
            this.name = name;
            this.id = id;
        }

        /// <summary>
        /// Prevents a default instance of the <see cref="Org"/> class from
        /// being created.
        /// </summary>
        private Org()
        {
        }

        /// <summary>
        /// Gets or sets the organization's name.
        /// </summary>
        /// <value>The organization's name.</value>
        [XmlAttribute]
        public string Name
        {
            get
            {
                return this.name;
            }

            set
            {
            }
        }

        /// <summary>
        /// Gets or sets the organization's ID.
        /// </summary>
        /// <value>The organization's ID.</value>
        [XmlAttribute]
        public int ID
        {
            get
            {
                return this.id;
            }

            set
            {
            }
        }
    }
}
Jesse C. Slicer
"The good news is the parameterless constructor can be private and the setters can be empty and serialization will work" I post this question to avoid that kind of "ugly fix". Ugly fix are really useful sometimes but I don't work alone so it's not always the best choice.
remi bourgarel