views:

145

answers:

5

I have a class:

public class Car {

   public string Model {get;set;}

   public string SeatFinish {get;set;}

   public string Audio {get;set;}
}

I want to use XML serialization attributes to serialize it to the following xml

<Car>
  <Model>name</Model>
  <Options>
   <SeatFinish>Leather</SeatFinish>
   <Audio>5 speaker</Audio>
  </Options>
</Car>

For reasons specific to the project i cannot just create a property:

public List<string> Options; 

Is there a way of specifying via attributes that a property is to be serialised under a certain xml Element (in this case an "Options" node)? Can I write a custom attribute that allows this? Any advice appreciated.

edit:

I see that having an options class will work but is there someway to acheive this without creating other classes? for example i might want to do this with only one property.

ideally i'd like to be able to specify

[Parent("Options")]
public string SeatFinish {get;set;}
+3  A: 

Is this part of a domain model or similar? It sounds like you're going to want these options to be re-useable outside of the car object, so why not create a separate Options class?

public class Options
{
   public string SeatFinish {get;set;}
   public string Audio {get;set;}
}

And change your Car class to hold the Options class:

public class Car 
{
   public string Model {get;set;}
   public Options Options {get;set;}
}
GenericTypeTea
i see this will work, but is there someway of doing this without creating an options class?
GreyCloud
I've never come across a way of doing it using just attributes.
GenericTypeTea
+1  A: 

If possible, try changing the class to this:

public class Car {

    public class CarOptions
    {
        public string SeatFinish { get; set; }
        public string Audio { get; set; }
    }

    public string Model { get; set; }
    public CarOptions Options { get; set; }

    public Car()
    {
        this.Options = new CarOptions();
    }
}
Codesleuth
@Codesleuth: `private set;` is not compatible with deserialization.
Ani
@Ani whoops, you're quite right. Force of habit.
Codesleuth
+1  A: 

I believe to get what you want you will need to implement IXmlSerializable and serialize the object yourself.

See: Custom XML Serialization.

First implement the interface:

public class Car : IXmlSerializable
{
    // Private state
    public string Model { get; set; }
    public string SeatFinish { get; set; }
    public string Audio { get; set; }

    public Car()
    {
        Model = "Toyota";
        SeatFinish = "Leather";
        Audio = "Awesome Soundz";
    }

...

Then implement your custom serialization. There are plenty of methods under the XmlWriter class to create the XML quickly and smartly however i've used WriteRaw() here for simplicity.

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteRaw("<Model>" + this.Model + "</Model>");
        writer.WriteRaw("<Options>");
        writer.WriteRaw("<SeatFinish>" + this.SeatFinish + "</SeatFinish>");
        writer.WriteRaw("<Audio>" + this.Audio + "</Audio>");
        writer.WriteRaw("</Options>");
    }

    public void ReadXml(XmlReader reader) { ... }
}

Then implement the corresponding ReadXml() method to deserialize your XML object representation. I would recommend using an System.Xml.XPath.XPathNavigator class to make the job of XML deserialization easier, but there are plenty of plain old methods in the XMLReader class anyway that you could probably get working for a contrived example.

hydrogen
A: 

I think that you are using the default XML serialization mechanics. In that case have a look on the IXmlSerializable Interface. It allows to add serialization hooks into the existing XML serialization mechanics. Then you can modify the XML representation without touching your existing object model.

Theo Lenndorff
A: 

Take a look at this previous post.

C# Serialization XML

I believe mixing it with what GenericTypeTea said is the best.

Hope it helps.

Vinícius Gobbo A. de Oliveira