views:

1893

answers:

5

Hello fellow coder,

Is there any way to serialize a property with an internal setter in C#?
I understand that this might be problematic - but if there is a way - I would like to know.

Example:

[Serializable]
public class Person
{
    public int ID { get; internal set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

Code that serializes an instance of the class Person:

Person person = new Person();
person.Age = 27;
person.Name = "Patrik";
person.ID = 1;

XmlSerializer serializer = new XmlSerializer(typeof(Person));
TextWriter writer = new StreamWriter(@"c:\test.xml");
serializer.Serialize(writer, person);
writer.Close();

Result (missing the ID property):

<?xml version="1.0" encoding="utf-8"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <Name>Patrik</Name>
  <Age>27</Age>
</Person>
+4  A: 

I think that the only alternative one way is to implement IXmlSerializable and do the object xml writing / parsing yourself.

Edit: After reading the comments, DataContractSerializer looks interesting ;)

Stormenet
Or use DataContractSerializer
Marc Gravell
I agree with Marc - please look at DataContractSerializer first as it will save you many headaches.
Andrew Hare
+1  A: 

If you're doing "default" XML serialization it will only look at public properties. Implementing IXmlSerializable will get you control over exactly what is serialized. If you're doing "standard" .NET serialization, it will look at fields - not properties, so your object will still be correctly serialized without any need for implementing any extra interfaces.

HTH, Kent

Kent Boogaart
By "standard" I assume you mean "BinaryFormatter"; in most ways, this is *less* standard, since xml serialization is supported on all the frameworks (CF, Silverlight, etc) - but BinaryFormatter isn't. Xml serialization is also more portable; or there are also 3rd-party portable binary serializers.
Marc Gravell
By "standard", I mean based on the standard .NET interfaces such as IFormatter. There is no reason an XML-based formatter cannot be used. Indeed, that's what SoapFormatter is.
Kent Boogaart
+1  A: 

Not that I've found without doing some work. I believe this is because the XmlSerializer that is generated uses reflection to generate a new class (which is in a new assembly, so cannot see internal member/methods).

There may be some mileage in using an XmlSerialization PreCompilier to generate the code, and then to modify it into an internal class for your purposes, so you'd then do something like:

XmlSerializer serializer = new MyPersonXmlSerializer();

The other option (and probably preferable) is to implement IXmlSerializable which will guide the auto-generated code to do the right thing.

Rowland Shaw
+19  A: 

If it is an option, DataContractSerializer (.NET 3.0) can serialize non-public properties:

[DataContract]
public class Person
{
    [DataMember]
    public int ID { get; internal set; }
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public int Age { get; set; }
}
...
static void Main()
{
    Person person = new Person();
    person.Age = 27;
    person.Name = "Patrik";
    person.ID = 1;

    DataContractSerializer serializer = new DataContractSerializer(typeof(Person));
    XmlWriter writer = XmlWriter.Create(@"c:\test.xml");
    serializer.WriteObject(writer, person);
    writer.Close();
}

With the xml (re-formatted):

<?xml version="1.0" encoding="utf-8"?>
<Person xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://schemas.datacontract.org/2004/07/"&gt;
    <Age>27</Age>
    <ID>1</ID>
    <Name>Patrik</Name>
</Person>
Marc Gravell
I wish I could upvote this twice
Andrew Hare
+1  A: 

You can implement IXmlSerializable, unfortunately this negates the most important benefit of XmlSerializer (the ability to declaratively control serialization). DataContractSerializer (xml based) and BinaryFormatter (binary based) could be used as alternatives to XmlSerializer each having its pros and cons.

Darin Dimitrov