XorPersist is an easy to use XML serialization library for .NET. With XorPersist, you can save your object graph to an XML file and restore it again later.
Table of Contents
- Features
- Usage
- Limitations
- Native support for most primitive data types and major .NET data and collection classes.
- Class inheritance and interfaces are fully supported.
- Data types without native support can be used by specifying custom serialization and deserialization.
- Customizable and extensible saving and loading of classes and properties.
- XSD schema validation for all input files.
- Classes without a public constructor are supported.
Supports sbyte
, byte
, short
, ushort
, int
, uint
, long
, ulong
, float
, double
, decimal
, bool
, char
and string
.
System.Guid
System.DateTime
System.TimeSpan
All types mentioned in the previous two sections are also supported when used as T for System.Nullable<T>
.
System.Collections.ArrayList
System.Collections.ICollection
System.Collections.IList
System.Collections.Generic.HashSet<T>
System.Collections.Generic.List<T>
System.Collections.Generic.SortedSet<T>
System.Collections.Generic.ICollection<T>
System.Collections.Generic.IList<T>
System.Collections.Generic.ISet<T>
System.Collections.Queue
System.Collections.Stack
System.Collections.Generic.LinkedList<T>
System.Collections.Generic.Queue<T>
System.Collections.Generic.Stack<T>
- Dictionaries can be used by storing the keys and values as two separate collections.
To use XorPersist, your class model must represent a tree. You need a root node that has no parent node and contains (by proxy) all other nodes. There can be diagonal references between nodes, but every node (aside from the root) must have exactly one parent node.
Derive your class from XorObject
and decorate it with an XorClassAttribute
:
using LateNightStupidities.XorPersist;
using LateNightStupidities.XorPersist.Attributes;
[XorClass(typeof(Company))]
class Company : XorObject { }
If you cannot directly derive your class from XorObject, you can also derive a base class of your class from XorObject.
The parameter of the XorClass
attribute defines which name your class is going to have in the XML file. You can specify a string or a System.Type
:
If you specify a type, the FullName of the type will be used. In migration scenarios between different versions of a data model,
it can be useful to specify a string instead of a type, because the type name might change.
In the next step, decorate all properties and fields you want to save with an XorPropertyAttribute
and define names for them:
[XorClass(typeof(Company))]
class Company : XorObject
{
[XorProperty("Name")]
public string Name { get; set; }
[XorProperty("YearEstablished")]
public int YearEstablished { get; set; }
}
All properties and fields that are decorated with an XorProperty
attribute will be saved. Obviously, a class can also contain other classes.
If your class is the direct parent of another class, use the XorProperty
attribute:
[XorProperty("Headquarter")]
public Building Headquarter { get; set; }
When the property does not hold a single instance or value, but is a collection, define the XorMultiplicity
List value.
A list of supported collection classes can be found in the Collection support section of this document.
[XorProperty("Employees", XorMultiplicity.List)]
public List<Employee> Employees { get; set; }
If your class only references another class but does not own it, or owns it, but in a different relationship (property),
use the XorReference
attribute. This will let XorPersist know,
that this is only a reference to the object, and not the parent-child relationship.
[XorReference("CEO")]
public Employee CEO { get; set; }
Like XorProperty
, the XorReference
attribute also supports collections:
[XorReference("BoardMembers", XorMultiplicity.List)
public List<Employee> BoardMembers { get; set; }
When you apply XorProperty
or XorReference
to a property, you don't need to specify the name. The name of the property will automatically be used.
This feature uses the CallerMemberNameAttribute that is available since .NET 4.5.
[XorProperty(XorMultiplicity.List)]
public List<Employee> Employees { get; set; }
[XorReference]
public Employee CEO { get; set; }
You still need to specify a name for fields. Not specifying a name for a field will result in an exception (InvalidXorAttributeNameException) during runtime:
// This will not work!
[XorProperty]
public string TestField;
When your data model is prepared for use with XorPersist, you can use the XorController
to load and restore the data.
// Saving:
Company myCompany = new Company();
XorController.Get().Save(myCompany, @"path/to/save.to");
// Restoring:
myCompany = XorController.Get().Load<Company>(@"path/to/load.from");
If an error occurs while saving or loading, an Exception will be raised. This can be an XorPersistException
when your data model does not provide all required information or contains another error, or other .NET exceptions.
See the Exceptions chapter in this document for more information.
XorPersist uses the base class XorPersistException
for all custom exception types.
This Exception is raised when XorPersist discovers a class that has no XorClass
attribute. The Exception text contains the affected class.
This Exception is raised when the target of stored reference cannot be found while loading a model. This happens if there are classes in the model that are only
referenced (XorReference
), so they have no owner. Every object in the model has to live in a XorProperty
property or field of another object.
This Exception is raised when XorPersist does not find a public parameterless constructor. For more information, see chapter Private or protected parameterless constructor in this document.
This Exception is raised when two different classes both define the same name in their XorClass
attribute.
This Exception is raised when XorPersist discovers a field or property with an unsupported data type. You can still use the data type with XorPersist, but you have to declare a 'conversion' property that uses a supported data type. In the following example, a custom string class property is serialized by a different property, that is only used by XorPersist.
[XorClass(typeof(CustomConversionExample))]
class CustomConversionExample : XorObject
{
// The type of this property is not supported...
public CustomString Description { get; set; }
// ... so the following property will perform
// the conversion to a supported data type.
[XorProperty("Description")]
private string _Description
{
get { return this.Description.ToString(); }
set { this.Description = new CustomString(value); }
}
}
This Exception is raised, when an invalid name is passed to an XorAttribute
constructor. Invalid names are:
null
- The empty string ("").
- A whitespace-only string (" ").
The InvalidXorAttributeNameException is also raised, when you apply an XorProperty
or XorReference
attribute to
a field (not a property) and don't specify a name.
This chapter lists a selection of system exceptions that may be raised by XorPersist.
- System.Xml.XmlException - This Exception may be raised when trying to load a model from a file that is not an XML file.
- System.IO.FileNotFoundException - This Exception may be raised when trying to load a model from a file path that does not exist.
- System.IO.IOException - This Exception may be raised when trying to load/save from/to a file that cannot be read/written. The access rights of the current user might be insufficient or the file might be opened in a different application.
This Exception is raised when trying to load a model from a file that is not valid according to the XorPersist XSD schema.
You do not have to declare a class that inherits from XorObject as a property type. You can also use an interface. XorPersist will detect the actual type used.
interface IVehicle { }
[XorClass(typeof(Car))]
class Car : XorObject, IVehicle { }
[XorClass(typeof(Truck))]
class Truck : XorObject, IVehicle { }
[XorClass(typeof(ParkingSpot))]
class ParkingSpot
{
[XorProperty("ParkedVehicle")]
IVehicle ParkedVehicle { get; set; }
}
You can perform custom actions before saving the model and after restoring the model. Override the appropriate methods of XorObject.
XorInitialize
is called after the whole model was restored. XorFinish
is called immediately before the object is serialized.
[XorClass(typeof(MyClass))]
class MyClass : XorObject
{
protected override void XorInitialize()
{
// ...
}
protected override void XorFinish()
{
// ...
}
}
A public parameterless constructor is needed to instantiate an unknown class. If you don't want to provide that in your data model,
you can also define the static _XorCreate()
method for XorPersist to use. This method can also be private.
[XorClass(typeof(MyClass))]
class MyClass : XorObject
{
private MyClass() { }
private static object _XorCreate()
{
return new MyClass();
}
}
- Dictionaries are not seamlessly supported.
- Workaround: Serialize the key and value collections separately.
- Generic types might not be fully supported.
Table of Contents generated with DocToc