Is it possible to serialize an internal setter of an object?

Is there a way to serialize a property with an internal installer in C #?
I understand that this can 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 Person class:

 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 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"> <Name>Patrik</Name> <Age>27</Age> </Person> 
+27
c # serialization
Jan 07 '09 at 15:10
source share
6 answers

If this 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(); } 

Using xml (reformatted):

 <?xml version="1.0" encoding="utf-8"?> <Person xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/"> <Age>27</Age> <ID>1</ID> <Name>Patrik</Name> </Person> 
+52
Jan 07 '09 at 15:23
source share

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

+5
Jan 07 '09 at 15:26
source share

I think the only one-way alternative is to implement IXmlSerializable and record the xml object / parsing itself.

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

+4
Jan 07 '09 at 15:18
source share

If you are serializing XML by default, it will only consider public properties. Implementing IXmlSerializable will allow you to control what is serialized. If you are doing β€œstandard” .NET serialization, it will consider fields, not properties, so your object will still be correctly serialized without the need for any additional interfaces.

+1
Jan 07 '09 at 15:20
source share

Not what I found without doing any work. I believe this is because the created XmlSerializer uses reflection to generate a new class (which is in the new assembly, therefore cannot see internal member / methods).

There may be a run in using XmlSerialization PreCompilier to generate the code and then change it into an inner class for your purposes, so you should do something like:

 XmlSerializer serializer = new MyPersonXmlSerializer(); 

Another option (and probably preferred) is the implementation of IXmlSerializable , which will direct the automatically generated code to work correctly.

+1
Jan 07 '09 at 15:21
source share

It is certainly possible. I want to illustrate a solution using XElement , which, by the way, I really liked. You do not need to use the XmlSerializer or DataContractSerializer or any class or property annotations, such as [DataContract] or [Serializable] , if you do not want to. In addition, the example below shows how you can exchange a private set for an internal set in my example, by the way:

 using System; using System.Linq; using System.Xml.Linq; namespace SerializationTesting { class Person { // Notice how this object type uses private setters, something that the traditional XmlSerializer will complain about if you don't use a wrapper class.. public string Name { get; private set; } public DateTime Birthday { get; private set; } public long HeightInMillimeters { get; private set; } public Gender Gendrality { get; private set; } // Generate a serialized XElement from this Person object. public XElement ToXElement() { return new XElement("person", new XAttribute("name", Name), new XAttribute("birthday", Birthday), new XAttribute("heightInMillimeters", HeightInMillimeters), new XAttribute("gendrality", (long)Gendrality) ); } // Serialize this Person object to an XElement. public static Person FromXElement(XElement x) { return new Person( (string)x.Attribute("name"), (DateTime)x.Attribute("birthday"), (long)x.Attribute("heightInMillimeters"), (Gender)(long)x.Attribute("gendrality") ); } public Person(string name, DateTime birthday, long heightInMillimeters, Gender gender) { Name = name; Birthday = birthday; HeightInMillimeters = heightInMillimeters; Gendrality = gender; } // You must override this in conjunction with overriding GetHashCode (below) if you want .NET collections (HashSet, List, etc.) to properly compare Person objects. public override bool Equals(object obj) { if (obj.GetType() == typeof(Person)) { Person objAsPerson = (Person)obj; return Name == objAsPerson.Name && Birthday == objAsPerson.Birthday && HeightInMillimeters == objAsPerson.HeightInMillimeters && Gendrality == objAsPerson.Gendrality; } return false; } // You must override this in conjunction with overriding Equals (above) if you want .NET collections (HashSet, List, etc.) to properly compare Person objects. public override int GetHashCode() { return Name.GetHashCode() ^ Birthday.GetHashCode() ^ HeightInMillimeters.GetHashCode() ^ Gendrality.GetHashCode(); } // This allows us to compare Person objects using the == operator. public static bool operator ==(Person a, Person b) { return a.Equals(b); } // This allows us to compate Person objects using the != operator. public static bool operator !=(Person a, Person b) { return !a.Equals(b); } } public enum Gender { Male, Female } class Program { static void Main(string[] args) { // Create first person (note how UTC time saves and loads properly when casting). Person personOne = new Person("Alexandru", DateTime.UtcNow, 1000, Gender.Male); // Save the first person to a local file on the hard disk. personOne.ToXElement().Save("PersonOne.dat"); // Create second person (not using UTC time this time around). Person personTwo = new Person("Alexandria", DateTime.Now, 900, Gender.Female); // Save the second person to a local file on the hard disk. personTwo.ToXElement().Save("PersonTwo.dat"); // Load the first person from a local file on the hard disk. XDocument personOneDocument = XDocument.Load("PersonOne.dat"); Person personOneLoadedFromDocument = Person.FromXElement(personOneDocument.Elements().First()); // Load the second person from a local file on the hard disk. XDocument personTwoDocument = XDocument.Load("PersonTwo.dat"); Person personTwoLoadedFromDocument = Person.FromXElement(personTwoDocument.Elements().First()); // Serialize the first person to a string and then load them from that string. string personOneString = personOne.ToXElement().ToString(); XDocument personOneDocumentFromString = XDocument.Parse(personOneString); Person personOneLoadedFromDocumentFromString = Person.FromXElement(personOneDocumentFromString.Elements().First()); // Check for equalities between persons (all outputs will be "true"). Console.WriteLine(personOne.Equals(personOneLoadedFromDocument)); Console.WriteLine(personTwo.Equals(personTwoLoadedFromDocument)); Console.WriteLine(personOne == personOneLoadedFromDocument); Console.WriteLine(personTwo == personTwoLoadedFromDocument); Console.WriteLine(personOne != personTwo); Console.WriteLine(personOneLoadedFromDocument != personTwoLoadedFromDocument); Console.WriteLine(personOne.Equals(personOneLoadedFromDocumentFromString)); Console.WriteLine("Press any key to exit."); Console.ReadKey(); } } } 

The result of all equality checks in the console application above will be true , as expected. This does not suffer from troubles, such as the need to track encodings or the way of analyzing data, because it does all of this for you, and it does not limit your class to public setters, as XmlSerializer does.

0
Dec 10 '14 at 22:43
source share



All Articles