spkl / xor-persist

XorPersist is an easy to use XML serialization library for .NET

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

xor-persist

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

  • 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.

Primitive data type support

Supports sbyte, byte, short, ushort, int, uint, long, ulong, float, double, decimal, bool, char and string.

Other supported .NET classes

  • System.Guid
  • System.DateTime
  • System.TimeSpan

Nullables

All types mentioned in the previous two sections are also supported when used as T for System.Nullable<T>.

Collection support

  • 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.

Usage

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.

Getting started

Preparing the data model

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;

Saving and restoring

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.

Exceptions

XorPersist uses the base class XorPersistException for all custom exception types.

ClassAttributeMissingException

This Exception is raised when XorPersist discovers a class that has no XorClass attribute. The Exception text contains the affected class.

CouldNotResolveReferenceException

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.

CtorMissingException

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.

DuplicateXorClassNameException

This Exception is raised when two different classes both define the same name in their XorClass attribute.

PropertyTypeNotSupportedException

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); }
    }
}
InvalidXorAttributeNameException

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.

Other Exceptions

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.
SchemaValidationException

This Exception is raised when trying to load a model from a file that is not valid according to the XorPersist XSD schema.

Interface usage

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; }
}

Custom serialization

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()
    {
        // ...
    }
}

Private or protected parameterless constructor

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

Limitations

  • 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

About

XorPersist is an easy to use XML serialization library for .NET

License:MIT License


Languages

Language:C# 100.0%