Why do you have to mark a class with the attribute [serializable]?
First off, you don't have to.
It is simply a marker interface that tells the serializer that the class is composed of items that it can serialize (which may or may not be true) and that is can use the default serialization.
The XMLSerializer
has the additional requirement to have a zero parameter constructor to the class.
There are other serializers that use contracts for serialization (such as the DataContractSerializer
) - they give you more control over serialization than simply marking a class as Serializable
. You can also get more control by implementing the ISerializable
interface.
Why isn't my public property serialized by the XmlSerializer?
As mentioned, most properties must have both a getter and setter; the main exception to this is lists - for example:
private readonly List<Foo> bar = new List<Foo>();
public List<Foo> Bar {get { return bar; } } // works fine
which will work fine; however, if XmlSerializer
finds a setter - it demands that it is public; the following will not work:
public List<Foo> Bar {get; private set;} // FAIL
Other reasons it might not serialize:
- it isn't public with get and set (or is
readonly
for a field) - it has a
[DefaultValue]
attribute, and is with that value - it has a public
bool ShouldSerializeFoo()
method that returned false - it has a public
bool FooSpecified {get;set;}
property or field that returned false - it is marked
[XmlIgnore]
- it is marked
[Obsolete]
Any of these will cause it not to serialize
C# force subclass to implement Serializable
The short answer is No you can't enforce an Attribute through an interface.
In principle, interfaces are about contracts (behaviour) while serialisation is about state which is not normally reflected in interfaces.
The options you have are:
Instead of using an interface for "storable" objects use an abstract class (like
StorableBase
) that consumer code should inherit from. Main drawback of this is that it restricts the types of classes the consumer code can use with your library. Also note that not all serialization libraries check all the class hierarchy when looking forSerializable
attribute and some might check only the concrete class. You can on top of that implement theISerializable
interface on that abstract class to have more control over the serialisation process. See here for details.Roslyn introduced the concept of Code Analyzers. You can create a custom code analyzer that checks at compile time for your rule. See here for more details and an example.
Unable to xml serialize custom object
Apparently you cannot serialize a type that inherits a non serializable type even ifyou do not wish to serialize the non-serializable properties of your derived type.
I think this should be classed as a bug since the who point of interfaces like ISerializable is to specify exactly what it is you inted to serialize by manually implementing the method that handles the serialization.
In any case the solution to my particular scenario was to not bother serializing at all and simply save the information of interest in to viewstate which would then be reused on postbacks to rebuild controls in the exact same state ready for the page based postback events to occur.
Shame this isnt better documented somewhere because although microsoft does document the SaveViewState and LoadViewState methods of the page lifecycle they are very vague about how these events might be used, i'm guessing they are hoping someone in the community might provide an example.
I would post my code but its a nasty hack to get everything working so i don't thing it should be mainstream msdn code.
Ok for a small internal app though :)
Why XML-Serializable class need a parameterless constructor
During an object's de-serialization, the class responsible for de-serializing an object creates an instance of the serialized class and then proceeds to populate the serialized fields and properties only after acquiring an instance to populate.
You can make your constructor private
or internal
if you want, just so long as it's parameterless.
XML Serialize generic list of serializable objects
I have an solution for a generic List<> with dynamic binded items.
class PersonalList it's the root element
[XmlRoot("PersonenListe")]
[XmlInclude(typeof(Person))] // include type class Person
public class PersonalList
{
[XmlArray("PersonenArray")]
[XmlArrayItem("PersonObjekt")]
public List<Person> Persons = new List<Person>();
[XmlElement("Listname")]
public string Listname { get; set; }
// Konstruktoren
public PersonalList() { }
public PersonalList(string name)
{
this.Listname = name;
}
public void AddPerson(Person person)
{
Persons.Add(person);
}
}
class Person it's an single list element
[XmlType("Person")] // define Type
[XmlInclude(typeof(SpecialPerson)), XmlInclude(typeof(SuperPerson))]
// include type class SpecialPerson and class SuperPerson
public class Person
{
[XmlAttribute("PersID", DataType = "string")]
public string ID { get; set; }
[XmlElement("Name")]
public string Name { get; set; }
[XmlElement("City")]
public string City { get; set; }
[XmlElement("Age")]
public int Age { get; set; }
// Konstruktoren
public Person() { }
public Person(string name, string city, int age, string id)
{
this.Name = name;
this.City = city;
this.Age = age;
this.ID = id;
}
}
class SpecialPerson inherits Person
[XmlType("SpecialPerson")] // define Type
public class SpecialPerson : Person
{
[XmlElement("SpecialInterests")]
public string Interests { get; set; }
public SpecialPerson() { }
public SpecialPerson(string name, string city, int age, string id, string interests)
{
this.Name = name;
this.City = city;
this.Age = age;
this.ID = id;
this.Interests = interests;
}
}
class SuperPerson inherits Person
[XmlType("SuperPerson")] // define Type
public class SuperPerson : Person
{
[XmlArray("Skills")]
[XmlArrayItem("Skill")]
public List<String> Skills { get; set; }
[XmlElement("Alias")]
public string Alias { get; set; }
public SuperPerson()
{
Skills = new List<String>();
}
public SuperPerson(string name, string city, int age, string id, string[] skills, string alias)
{
Skills = new List<String>();
this.Name = name;
this.City = city;
this.Age = age;
this.ID = id;
foreach (string item in skills)
{
this.Skills.Add(item);
}
this.Alias = alias;
}
}
and the main test Source
static void Main(string[] args)
{
PersonalList personen = new PersonalList();
personen.Listname = "Friends";
// normal person
Person normPerson = new Person();
normPerson.ID = "0";
normPerson.Name = "Max Man";
normPerson.City = "Capitol City";
normPerson.Age = 33;
// special person
SpecialPerson specPerson = new SpecialPerson();
specPerson.ID = "1";
specPerson.Name = "Albert Einstein";
specPerson.City = "Ulm";
specPerson.Age = 36;
specPerson.Interests = "Physics";
// super person
SuperPerson supPerson = new SuperPerson();
supPerson.ID = "2";
supPerson.Name = "Superman";
supPerson.Alias = "Clark Kent";
supPerson.City = "Metropolis";
supPerson.Age = int.MaxValue;
supPerson.Skills.Add("fly");
supPerson.Skills.Add("strong");
// Add Persons
personen.AddPerson(normPerson);
personen.AddPerson(specPerson);
personen.AddPerson(supPerson);
// Serialize
Type[] personTypes = { typeof(Person), typeof(SpecialPerson), typeof(SuperPerson) };
XmlSerializer serializer = new XmlSerializer(typeof(PersonalList), personTypes);
FileStream fs = new FileStream("Personenliste.xml", FileMode.Create);
serializer.Serialize(fs, personen);
fs.Close();
personen = null;
// Deserialize
fs = new FileStream("Personenliste.xml", FileMode.Open);
personen = (PersonalList)serializer.Deserialize(fs);
serializer.Serialize(Console.Out, personen);
Console.ReadLine();
}
Important is the definition and includes of the diffrent types.
Class Serialization To XML
XMLSerializer doesn't support Dictionary out of the box. Your UserCollection class has a Dictionary. See this link for a workaround.
Why doesn't XmlSerializer support Dictionary?
Other than that the XMLSerializer requires that your classes have default constructors (UserCollection and User don't) and each of them must have the [Serializable] attribute.
Related Topics
How to Test Smtpclient Before Calling Client.Send()
Giving Application Elevated Uac
Binding Selecteditems of Listview to Viewmodel
Regex: Repeated Capturing Groups
Getting Variable by Name in C#
Show Yes/No Instead True/False in Datagridview
C# How to Loop User Input Until the Datatype of the Input Is Correct
How to Add Option Groups in ASP.NET Drop Down List
Disable Transitive Project Reference in .Net Standard 2
How to Output Unicode String to Rtf (Using C#)
Mongodb .Net Driver 2.0 Pull (Remove Element)
Select Either a File or Folder from the Same Dialog in .Net
Problems Overwriting (Re-Saving) Image When It Was Set as Image Source
How to Write a Transaction to Cover Moving a File and Inserting Record in Database